Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HTTP API version 1 #91

Merged
merged 6 commits into from
Dec 20, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ allprojects {

// Common repositories.
repositories {
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
mavenCentral()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.linecorp.centraldogma.common;

import static com.linecorp.centraldogma.internal.Util.validateFilePath;
import static java.util.Objects.requireNonNull;

import java.util.Collections;
Expand All @@ -31,7 +32,7 @@ final class IdentityQuery implements Query<Object> {

@JsonCreator
IdentityQuery(@JsonProperty("path") String path) {
this.path = requireNonNull(path, "path");
this.path = validateFilePath(path, "path");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.linecorp.centraldogma.common;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.linecorp.centraldogma.internal.Util.validateJsonFilePath;
import static java.util.Objects.requireNonNull;

import java.util.List;
Expand All @@ -38,21 +39,18 @@ final class JsonPathQuery implements Query<JsonNode> {
private String strVal;

JsonPathQuery(String path, String... jsonPaths) {
requireNonNull(path, "path");
requireNonNull(jsonPaths, "jsonPaths");

this.path = path;
this.path = validateJsonFilePath(path, "path");
this.jsonPaths = Stream.of(jsonPaths).peek(JsonPathQuery::validateJsonPath).collect(toImmutableList());
}

@JsonCreator
JsonPathQuery(@JsonProperty("path") String path,
@JsonProperty("expressions") Iterable<String> jsonPaths) {

requireNonNull(path, "path");
requireNonNull(jsonPaths, "jsonPaths");

this.path = path;
this.path = validateJsonFilePath(path, "path");
this.jsonPaths = Streams.stream(jsonPaths)
.peek(JsonPathQuery::validateJsonPath)
.collect(toImmutableList());
Expand Down
26 changes: 26 additions & 0 deletions common/src/main/java/com/linecorp/centraldogma/common/Markup.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
package com.linecorp.centraldogma.common;

import static com.google.common.base.Strings.isNullOrEmpty;

import javax.annotation.Nullable;

import com.google.common.base.Ascii;

/**
Expand Down Expand Up @@ -46,4 +50,26 @@ public enum Markup {
public String nameLowercased() {
return nameLowercased;
}

/**
* Returns a {@link Markup} from the specified {@code value}. If none of markup is matched,
* this will return {@link #UNKNOWN}.
*/
public static Markup parse(@Nullable String value) {
if (isNullOrEmpty(value)) {
return UNKNOWN;
}

final String markup = Ascii.toUpperCase(value);

if ("PLAINTEXT".equalsIgnoreCase(markup)) {
return PLAINTEXT;
}

if ("MARKDOWN".equalsIgnoreCase(markup)) {
return MARKDOWN;
}

return UNKNOWN;
}
}
12 changes: 6 additions & 6 deletions common/src/main/java/com/linecorp/centraldogma/common/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import com.fasterxml.jackson.databind.JsonNode;

/**
* A query on an {@link Entry}.
* A query on a file.
*
* @param <T> the content type of an {@link Entry} being queried
* @param <T> the content type of a file being queried
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
Expand All @@ -44,7 +44,7 @@ public interface Query<T> extends Function<T, T> {
/**
* Returns a newly-created {@link Query} that retrieves the content as it is.
*
* @param path the path of the {@link Entry} being queried on
* @param path the path of a file being queried on
*/
static Query<Object> identity(String path) {
return new IdentityQuery(path);
Expand All @@ -55,7 +55,7 @@ static Query<Object> identity(String path) {
* <a href="https://github.com/json-path/JsonPath/blob/master/README.md">JSON path expressions</a>
* to the content.
*
* @param path the path of the {@link Entry} being queried on
* @param path the path of a file being queried on
* @param jsonPaths the JSON path expressions to apply
*/
static Query<JsonNode> ofJsonPath(String path, String... jsonPaths) {
Expand All @@ -67,7 +67,7 @@ static Query<JsonNode> ofJsonPath(String path, String... jsonPaths) {
* <a href="https://github.com/json-path/JsonPath/blob/master/README.md">JSON path expressions</a>
* to the content.
*
* @param path the path of the {@link Entry} being queried on
* @param path the path of a file being queried on
* @param jsonPaths the JSON path expressions to apply
*/
static Query<JsonNode> ofJsonPath(String path, Iterable<String> jsonPaths) {
Expand All @@ -78,7 +78,7 @@ static Query<JsonNode> ofJsonPath(String path, Iterable<String> jsonPaths) {
* Returns a newly-created {@link Query} that applies a series of expressions to the content.
*
* @param type the type of the {@link Query}
* @param path the path of the {@link Entry} being queried
* @param path the path of a file being queried on
* @param expressions the expressions to apply
*/
static Query<?> of(QueryType type, String path, @Nullable String... expressions) {
Expand Down
35 changes: 30 additions & 5 deletions common/src/main/java/com/linecorp/centraldogma/internal/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public final class Util {
"^(?:[-_0-9a-zA-Z](?:[-_\\.0-9a-zA-Z]*[-_0-9a-zA-Z])?)+$");
private static final Pattern FILE_PATH_PATTERN = Pattern.compile(
"^(?:/[-_0-9a-zA-Z](?:[-_\\.0-9a-zA-Z]*[-_0-9a-zA-Z])?)+$");
private static final Pattern JSON_FILE_PATH_PATTERN = Pattern.compile(
"^(?:/[-_0-9a-zA-Z](?:[-_\\.0-9a-zA-Z]*[-_0-9a-zA-Z])?)+\\.(?i)json$");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we treat .JSON as JSON? IIRC we only accept .json, but my memory may not be correct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not know. That was just my decision. I will remove the (?i) :-)

Copy link
Member

@trustin trustin Dec 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it seems case-insensitive. In EntryType:

    /**
     * Guesses the {@link EntryType} from the specified {@code path}.
     */
    public static EntryType guessFromPath(String path) {
        requireNonNull(path, "path");
        if (path.isEmpty()) {
            throw new IllegalArgumentException("empty path");
        }

        if (path.charAt(path.length() - 1) == '/') {
            return DIRECTORY;
        }

        if (Ascii.toLowerCase(path).endsWith(".json")) {
            return JSON;
        }

        return TEXT;
    }

Sorry!

private static final Pattern DIR_PATH_PATTERN = Pattern.compile(
"^(?:/[-_0-9a-zA-Z](?:[-_\\.0-9a-zA-Z]*[-_0-9a-zA-Z])?)*/?$");
private static final Pattern EMAIL_PATTERN = Pattern.compile(
Expand All @@ -55,6 +57,11 @@ public static String validateFileName(String name, String paramName) {
paramName + ": " + name + " (expected: " + FILE_NAME_PATTERN.pattern() + ')');
}

public static boolean isValidFileName(String name) {
requireNonNull(name, "name");
return !name.isEmpty() && FILE_NAME_PATTERN.matcher(name).matches();
}

public static String validateFilePath(String path, String paramName) {
requireNonNull(path, paramName);
if (isValidFilePath(path)) {
Expand All @@ -65,17 +72,28 @@ public static String validateFilePath(String path, String paramName) {
paramName + ": " + path + " (expected: " + FILE_PATH_PATTERN.pattern() + ')');
}

public static boolean isValidFileName(String name) {
requireNonNull(name, "name");
return !name.isEmpty() && FILE_NAME_PATTERN.matcher(name).matches();
}

public static boolean isValidFilePath(String path) {
requireNonNull(path, "path");
return !path.isEmpty() && path.charAt(0) == '/' &&
FILE_PATH_PATTERN.matcher(path).matches();
}

public static String validateJsonFilePath(String path, String paramName) {
requireNonNull(path, paramName);
if (isValidJsonFilePath(path)) {
return path;
}

throw new IllegalArgumentException(
paramName + ": " + path + " (expected: " + JSON_FILE_PATH_PATTERN.pattern() + ')');
}

public static boolean isValidJsonFilePath(String path) {
requireNonNull(path, "path");
return !path.isEmpty() && path.charAt(0) == '/' &&
JSON_FILE_PATH_PATTERN.matcher(path).matches();
}

public static String validateDirPath(String path, String paramName) {
requireNonNull(path, paramName);
if (isValidDirPath(path)) {
Expand All @@ -87,7 +105,14 @@ public static String validateDirPath(String path, String paramName) {
}

public static boolean isValidDirPath(String path) {
return isValidDirPath(path, false);
}

public static boolean isValidDirPath(String path, boolean mustEndWithSlash) {
requireNonNull(path);
if (mustEndWithSlash && !path.endsWith("/")) {
return false;
}
return !path.isEmpty() && path.charAt(0) == '/' &&
DIR_PATH_PATTERN.matcher(path).matches();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2017 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.centraldogma.internal.httpapi.v1;

import static java.util.Objects.requireNonNull;

import javax.annotation.Nullable;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;

import com.linecorp.centraldogma.common.ChangeType;

@JsonInclude(Include.NON_NULL)
public class ChangeDto<T> {

private final String path;

private final ChangeType type;

private final T content;

public ChangeDto(String path, ChangeType type, @Nullable T content) {
this.path = requireNonNull(path, "path");
this.type = requireNonNull(type, "type");
this.content = content;
}

@JsonProperty("path")
public String path() {
return path;
}

@JsonProperty("type")
public ChangeType type() {
return type;
}

@Nullable
@JsonProperty("content")
public T content() {
return content;
}

@Override
public String toString() {
final ToStringHelper stringHelper = MoreObjects.toStringHelper(this)
.add("path", path())
.add("type", type());
if (content() != null) {
stringHelper.add("content", content());
}

return stringHelper.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2017 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.centraldogma.internal.httpapi.v1;

import static java.time.format.DateTimeFormatter.ISO_INSTANT;
import static java.util.Objects.requireNonNull;

import java.time.Instant;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;

import com.linecorp.centraldogma.common.Author;
import com.linecorp.centraldogma.common.Commit;
import com.linecorp.centraldogma.common.Revision;

public class CommitDto {

private final Revision revision;

private final Author author;

private final CommitMessageDto commitMessage;

private final String pushedAt;

public CommitDto(Commit commit) {
requireNonNull(commit, "commit");
revision = commit.revision();
author = commit.author();
commitMessage = new CommitMessageDto(commit.summary(), commit.detail(), commit.markup());
pushedAt = ISO_INSTANT.format(Instant.ofEpochMilli(commit.when()));
}

@JsonProperty("revision")
public Revision revision() {
return revision;
}

@JsonProperty("author")
public Author author() {
return author;
}

@JsonProperty("pushedAt")
public String pushedAt() {
return pushedAt;
}

@JsonProperty("commitMessage")
public CommitMessageDto commitMessage() {
return commitMessage;
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("revision", revision())
.add("author", author())
.add("commitMessage", commitMessage())
.add("pushedAt", pushedAt())
.toString();
}
}
Loading