1   /*
2    * Copyright 2021 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package com.linecorp.centraldogma.client;
17  
18  import static java.util.Objects.requireNonNull;
19  
20  import java.util.Objects;
21  import java.util.concurrent.CompletableFuture;
22  import java.util.concurrent.ScheduledExecutorService;
23  
24  import com.google.common.base.MoreObjects;
25  import com.google.common.collect.ImmutableList;
26  
27  import com.linecorp.centraldogma.common.Change;
28  import com.linecorp.centraldogma.common.Markup;
29  import com.linecorp.centraldogma.common.MergeQuery;
30  import com.linecorp.centraldogma.common.MergeSource;
31  import com.linecorp.centraldogma.common.PathPattern;
32  import com.linecorp.centraldogma.common.Query;
33  import com.linecorp.centraldogma.common.QueryType;
34  import com.linecorp.centraldogma.common.Revision;
35  
36  /**
37   * Prepares to send requests to the Central Dogma repository.
38   */
39  public final class CentralDogmaRepository {
40  
41      private final CentralDogma centralDogma;
42      private final String projectName;
43      private final String repositoryName;
44      private final ScheduledExecutorService blockingTaskExecutor;
45  
46      CentralDogmaRepository(CentralDogma centralDogma, String projectName, String repositoryName,
47                             ScheduledExecutorService blockingTaskExecutor) {
48          this.centralDogma = centralDogma;
49          this.projectName = projectName;
50          this.repositoryName = repositoryName;
51          this.blockingTaskExecutor = blockingTaskExecutor;
52      }
53  
54      CentralDogma centralDogma() {
55          return centralDogma;
56      }
57  
58      String projectName() {
59          return projectName;
60      }
61  
62      String repositoryName() {
63          return repositoryName;
64      }
65  
66      /**
67       * Converts the relative revision number to the absolute revision number. e.g. {@code -1 -> 3}
68       *
69       * @return the absolute {@link Revision}
70       */
71      public CompletableFuture<Revision> normalize(Revision revision) {
72          requireNonNull(revision, "revision");
73          return centralDogma.normalizeRevision(projectName, repositoryName, revision);
74      }
75  
76      /**
77       * Returns a new {@link FileRequest} that is used to retrieve the file in the Central Dogma repository.
78       * Call {@link FileRequest#get(Revision)} to perform the same operation as
79       * {@link CentralDogma#getFile(String, String, Revision, Query)}.
80       */
81      public FileRequest<?> file(String path) {
82          requireNonNull(path, "path");
83          return file(Query.of(QueryType.IDENTITY, path));
84      }
85  
86      /**
87       * Returns a new {@link FileRequest} that is used to retrieve the file in the Central Dogma repository.
88       * Call {@link FileRequest#get(Revision)} to perform the same operation as
89       * {@link CentralDogma#getFile(String, String, Revision, Query)}.
90       */
91      public <T> FileRequest<T> file(Query<T> query) {
92          requireNonNull(query, "query");
93          return new FileRequest<>(this, query);
94      }
95  
96      /**
97       * Returns a new {@link FilesRequest} that is used to retrieve or list files in the
98       * Central Dogma repository.
99       * Call {@link FilesRequest#get(Revision)} or {@link FilesRequest#list(Revision)} for those operation.
100      */
101     public FilesRequest file(PathPattern pathPattern) {
102         requireNonNull(pathPattern, "pathPattern");
103         return new FilesRequest(this, pathPattern);
104     }
105 
106     /**
107      * Returns a new {@link MergeRequest} that is used to retrieve the merged file in the
108      * Central Dogma repository.
109      * Call {@link MergeRequest#get(Revision)} to perform the same operation as
110      * {@link CentralDogma#mergeFiles(String, String, Revision, MergeQuery)}.
111      */
112     public MergeRequest<?> merge(MergeSource... mergeSources) {
113         requireNonNull(mergeSources, "mergeSources");
114         return merge(ImmutableList.copyOf(mergeSources));
115     }
116 
117     /**
118      * Returns a new {@link MergeRequest} that is used to retrieve the merged file in the
119      * Central Dogma repository.
120      * Call {@link MergeRequest#get(Revision)} to perform the same operation as
121      * {@link CentralDogma#mergeFiles(String, String, Revision, MergeQuery)}.
122      */
123     public MergeRequest<?> merge(Iterable<MergeSource> mergeSources) {
124         requireNonNull(mergeSources, "mergeSources");
125         return merge(MergeQuery.ofJson(mergeSources));
126     }
127 
128     /**
129      * Returns a new {@link MergeRequest} that is used to retrieve the merged file in the
130      * Central Dogma repository.
131      * Call {@link MergeRequest#get(Revision)} to perform the same operation as
132      * {@link CentralDogma#mergeFiles(String, String, Revision, MergeQuery)}.
133      */
134     public <T> MergeRequest<T> merge(MergeQuery<T> mergeQuery) {
135         requireNonNull(mergeQuery, "mergeQuery");
136         return new MergeRequest<>(this, mergeQuery);
137     }
138 
139     /**
140      * Returns a new {@link HistoryRequest} that is used to retrieve the history of all files in the
141      * Central Dogma repository.
142      * Call {@link HistoryRequest#get(Revision, Revision)} to perform the same operation as
143      * {@link CentralDogma#getHistory(String, String, Revision, Revision, PathPattern, int)}.
144      */
145     public HistoryRequest history() {
146         return history(PathPattern.all());
147     }
148 
149     /**
150      * Returns a new {@link HistoryRequest} that is used to retrieve the history of files in the
151      * Central Dogma repository.
152      * Call {@link HistoryRequest#get(Revision, Revision)} to perform the same operation as
153      * {@link CentralDogma#getHistory(String, String, Revision, Revision, PathPattern, int)}.
154      */
155     public HistoryRequest history(PathPattern pathPattern) {
156         requireNonNull(pathPattern, "pathPattern");
157         return new HistoryRequest(this, pathPattern);
158     }
159 
160     /**
161      * Returns a new {@link DiffRequest} that is used to retrieve the diff of the file in the
162      * Central Dogma repository.
163      * Call {@link DiffRequest#get(Revision, Revision)} to perform the same operation as
164      * {@link CentralDogma#getDiff(String, String, Revision, Revision, Query)}.
165      */
166     public DiffRequest<?> diff(String path) {
167         requireNonNull(path, "path");
168         return diff(Query.of(QueryType.IDENTITY, path));
169     }
170 
171     /**
172      * Returns a new {@link DiffRequest} that is used to retrieve the diff of the file in the
173      * Central Dogma repository.
174      * Call {@link DiffRequest#get(Revision, Revision)} to perform the same operation as
175      * {@link CentralDogma#getDiff(String, String, Revision, Revision, Query)}.
176      */
177     public <T> DiffRequest<T> diff(Query<T> query) {
178         requireNonNull(query, "query");
179         return new DiffRequest<>(this, query);
180     }
181 
182     /**
183      * Returns a new {@link DiffFilesRequest} that is used to retrieve the diff of files in the
184      * Central Dogma repository.
185      * Call {@link DiffFilesRequest#get(Revision, Revision)} to perform the same operation as
186      * {@link CentralDogma#getDiff(String, String, Revision, Revision, PathPattern)}.
187      */
188     public DiffFilesRequest diff(PathPattern pathPattern) {
189         requireNonNull(pathPattern, "pathPattern");
190         return new DiffFilesRequest(this, pathPattern);
191     }
192 
193     /**
194      * Returns a new {@link PreviewDiffRequest} that is used to retrieve the preview diff of files in the
195      * Central Dogma repository.
196      * Call {@link PreviewDiffRequest#get(Revision)} to perform the same operation as
197      * {@link CentralDogma#getPreviewDiffs(String, String, Revision, Iterable)}.
198      */
199     public PreviewDiffRequest diff(Change<?>... changes) {
200         requireNonNull(changes, "changes");
201         return new PreviewDiffRequest(this, ImmutableList.copyOf(changes));
202     }
203 
204     /**
205      * Returns a new {@link PreviewDiffRequest} that is used to retrieve the preview diff of files in the
206      * Central Dogma repository.
207      * Call {@link PreviewDiffRequest#get(Revision)} to perform the same operation as
208      * {@link CentralDogma#getPreviewDiffs(String, String, Revision, Iterable)}.
209      */
210     public PreviewDiffRequest diff(Iterable<? extends Change<?>> changes) {
211         requireNonNull(changes, "changes");
212         return new PreviewDiffRequest(this, changes);
213     }
214 
215     /**
216      * Returns a new {@link CommitRequest} that is used to push the {@link Change}s to the
217      * Central Dogma repository.
218      * Call {@link CommitRequest#push(Revision)} to perform the same operation as
219      * {@link CentralDogma#push(String, String, Revision, String, String, Markup, Iterable)}.
220      */
221     public CommitRequest commit(String summary, Change<?>... changes) {
222         requireNonNull(changes, "changes");
223         return commit(summary, ImmutableList.copyOf(changes));
224     }
225 
226     /**
227      * Returns a new {@link CommitRequest} that is used to push the {@link Change}s to the
228      * Central Dogma repository.
229      * Call {@link CommitRequest#push(Revision)} to perform the same operation as
230      * {@link CentralDogma#push(String, String, Revision, String, String, Markup, Iterable)}.
231      */
232     public CommitRequest commit(String summary, Iterable<? extends Change<?>> changes) {
233         requireNonNull(summary, "summary");
234         requireNonNull(changes, "changes");
235         return new CommitRequest(this, summary, changes);
236     }
237 
238     /**
239      * Returns a new {@link WatchRequest} that is used to watch the file in the
240      * Central Dogma repository.
241      * Call {@link WatchRequest#start(Revision)} to perform the same operation as
242      * {@link CentralDogma#watchFile(String, String, Revision, Query, long, boolean)}.
243      */
244     public WatchRequest<?> watch(String path) {
245         requireNonNull(path, "path");
246         return watch(Query.of(QueryType.IDENTITY, path));
247     }
248 
249     /**
250      * Returns a new {@link WatchRequest} that is used to watch the file in the
251      * Central Dogma repository.
252      * Call {@link WatchRequest#start(Revision)} to perform the same operation as
253      * {@link CentralDogma#watchFile(String, String, Revision, Query, long, boolean)}.
254      */
255     public <T> WatchRequest<T> watch(Query<T> query) {
256         requireNonNull(query, "query");
257         return new WatchRequest<>(this, query);
258     }
259 
260     /**
261      * Returns a new {@link WatchFilesRequest} that is used to watch the files in the
262      * Central Dogma repository.
263      * Call {@link WatchFilesRequest#start(Revision)} to perform the same operation as
264      * {@link CentralDogma#watchRepository(String, String, Revision, PathPattern, long, boolean)}.
265      */
266     public WatchFilesRequest watch(PathPattern pathPattern) {
267         requireNonNull(pathPattern, "pathPattern");
268         return new WatchFilesRequest(this, pathPattern);
269     }
270 
271     /**
272      * Returns a new {@link WatcherRequest} that is used to create a {@link Watcher}.
273      */
274     public <T> WatcherRequest<T> watcher(Query<T> query) {
275         requireNonNull(query, "query");
276         return new WatcherRequest<>(this, query, blockingTaskExecutor);
277     }
278 
279     /**
280      * Returns a new {@link WatcherRequest} that is used to create a {@link Watcher}.
281      */
282     public WatcherRequest<Revision> watcher(PathPattern pathPattern) {
283         requireNonNull(pathPattern, "pathPattern");
284         return new WatcherRequest<>(this, pathPattern, blockingTaskExecutor);
285     }
286 
287     @Override
288     public boolean equals(Object o) {
289         if (this == o) {
290             return true;
291         }
292         if (!(o instanceof CentralDogmaRepository)) {
293             return false;
294         }
295         final CentralDogmaRepository that = (CentralDogmaRepository) o;
296         return centralDogma == that.centralDogma &&
297                projectName.equals(that.projectName) && repositoryName.equals(that.repositoryName) &&
298                blockingTaskExecutor == that.blockingTaskExecutor;
299     }
300 
301     @Override
302     public int hashCode() {
303         return Objects.hash(centralDogma, projectName, repositoryName, blockingTaskExecutor);
304     }
305 
306     @Override
307     public String toString() {
308         return MoreObjects.toStringHelper(this)
309                           .add("centralDogma", centralDogma)
310                           .add("projectName", projectName)
311                           .add("repositoryName", repositoryName)
312                           .add("blockingTaskExecutor", blockingTaskExecutor)
313                           .toString();
314     }
315 }