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 javax.annotation.Nullable;
25  
26  import com.google.common.base.MoreObjects;
27  import com.google.common.collect.ImmutableList;
28  
29  import com.linecorp.centraldogma.common.Change;
30  import com.linecorp.centraldogma.common.Markup;
31  import com.linecorp.centraldogma.common.MergeQuery;
32  import com.linecorp.centraldogma.common.MergeSource;
33  import com.linecorp.centraldogma.common.PathPattern;
34  import com.linecorp.centraldogma.common.Query;
35  import com.linecorp.centraldogma.common.QueryType;
36  import com.linecorp.centraldogma.common.Revision;
37  
38  import io.micrometer.core.instrument.MeterRegistry;
39  
40  /**
41   * Prepares to send requests to the Central Dogma repository.
42   */
43  public final class CentralDogmaRepository {
44  
45      private final CentralDogma centralDogma;
46      private final String projectName;
47      private final String repositoryName;
48      private final ScheduledExecutorService blockingTaskExecutor;
49      @Nullable
50      private final MeterRegistry meterRegistry;
51  
52      CentralDogmaRepository(CentralDogma centralDogma, String projectName, String repositoryName,
53                             ScheduledExecutorService blockingTaskExecutor,
54                             @Nullable MeterRegistry meterRegistry) {
55          this.centralDogma = centralDogma;
56          this.projectName = projectName;
57          this.repositoryName = repositoryName;
58          this.blockingTaskExecutor = blockingTaskExecutor;
59          this.meterRegistry = meterRegistry;
60      }
61  
62      CentralDogma centralDogma() {
63          return centralDogma;
64      }
65  
66      /**
67       * Returns the name of the project.
68       */
69      public String projectName() {
70          return projectName;
71      }
72  
73      /**
74       * Returns the name of the repository.
75       */
76      public String repositoryName() {
77          return repositoryName;
78      }
79  
80      /**
81       * Converts the relative revision number to the absolute revision number. e.g. {@code -1 -> 3}
82       *
83       * @return the absolute {@link Revision}
84       */
85      public CompletableFuture<Revision> normalize(Revision revision) {
86          requireNonNull(revision, "revision");
87          return centralDogma.normalizeRevision(projectName, repositoryName, revision);
88      }
89  
90      /**
91       * Returns a new {@link FileRequest} that is used to retrieve the file in the Central Dogma repository.
92       * Call {@link FileRequest#get(Revision)} to perform the same operation as
93       * {@link CentralDogma#getFile(String, String, Revision, Query)}.
94       */
95      public FileRequest<?> file(String path) {
96          requireNonNull(path, "path");
97          return file(Query.of(QueryType.IDENTITY, path));
98      }
99  
100     /**
101      * Returns a new {@link FileRequest} that is used to retrieve the file in the Central Dogma repository.
102      * Call {@link FileRequest#get(Revision)} to perform the same operation as
103      * {@link CentralDogma#getFile(String, String, Revision, Query)}.
104      */
105     public <T> FileRequest<T> file(Query<T> query) {
106         requireNonNull(query, "query");
107         return new FileRequest<>(this, query);
108     }
109 
110     /**
111      * Returns a new {@link FilesRequest} that is used to retrieve or list files in the
112      * Central Dogma repository.
113      * Call {@link FilesRequest#get(Revision)} or {@link FilesRequest#list(Revision)} for those operation.
114      */
115     public FilesRequest file(PathPattern pathPattern) {
116         requireNonNull(pathPattern, "pathPattern");
117         return new FilesRequest(this, pathPattern);
118     }
119 
120     /**
121      * Returns a new {@link MergeRequest} that is used to retrieve the merged file in the
122      * Central Dogma repository.
123      * Call {@link MergeRequest#get(Revision)} to perform the same operation as
124      * {@link CentralDogma#mergeFiles(String, String, Revision, MergeQuery)}.
125      */
126     public MergeRequest<?> merge(MergeSource... mergeSources) {
127         requireNonNull(mergeSources, "mergeSources");
128         return merge(ImmutableList.copyOf(mergeSources));
129     }
130 
131     /**
132      * Returns a new {@link MergeRequest} that is used to retrieve the merged file in the
133      * Central Dogma repository.
134      * Call {@link MergeRequest#get(Revision)} to perform the same operation as
135      * {@link CentralDogma#mergeFiles(String, String, Revision, MergeQuery)}.
136      */
137     public MergeRequest<?> merge(Iterable<MergeSource> mergeSources) {
138         requireNonNull(mergeSources, "mergeSources");
139         return merge(MergeQuery.ofJson(mergeSources));
140     }
141 
142     /**
143      * Returns a new {@link MergeRequest} that is used to retrieve the merged file in the
144      * Central Dogma repository.
145      * Call {@link MergeRequest#get(Revision)} to perform the same operation as
146      * {@link CentralDogma#mergeFiles(String, String, Revision, MergeQuery)}.
147      */
148     public <T> MergeRequest<T> merge(MergeQuery<T> mergeQuery) {
149         requireNonNull(mergeQuery, "mergeQuery");
150         return new MergeRequest<>(this, mergeQuery);
151     }
152 
153     /**
154      * Returns a new {@link HistoryRequest} that is used to retrieve the history of all files in the
155      * Central Dogma repository.
156      * Call {@link HistoryRequest#get(Revision, Revision)} to perform the same operation as
157      * {@link CentralDogma#getHistory(String, String, Revision, Revision, PathPattern, int)}.
158      */
159     public HistoryRequest history() {
160         return history(PathPattern.all());
161     }
162 
163     /**
164      * Returns a new {@link HistoryRequest} that is used to retrieve the history of files in the
165      * Central Dogma repository.
166      * Call {@link HistoryRequest#get(Revision, Revision)} to perform the same operation as
167      * {@link CentralDogma#getHistory(String, String, Revision, Revision, PathPattern, int)}.
168      */
169     public HistoryRequest history(PathPattern pathPattern) {
170         requireNonNull(pathPattern, "pathPattern");
171         return new HistoryRequest(this, pathPattern);
172     }
173 
174     /**
175      * Returns a new {@link DiffRequest} that is used to retrieve the diff of the file in the
176      * Central Dogma repository.
177      * Call {@link DiffRequest#get(Revision, Revision)} to perform the same operation as
178      * {@link CentralDogma#getDiff(String, String, Revision, Revision, Query)}.
179      */
180     public DiffRequest<?> diff(String path) {
181         requireNonNull(path, "path");
182         return diff(Query.of(QueryType.IDENTITY, path));
183     }
184 
185     /**
186      * Returns a new {@link DiffRequest} that is used to retrieve the diff of the file in the
187      * Central Dogma repository.
188      * Call {@link DiffRequest#get(Revision, Revision)} to perform the same operation as
189      * {@link CentralDogma#getDiff(String, String, Revision, Revision, Query)}.
190      */
191     public <T> DiffRequest<T> diff(Query<T> query) {
192         requireNonNull(query, "query");
193         return new DiffRequest<>(this, query);
194     }
195 
196     /**
197      * Returns a new {@link DiffFilesRequest} that is used to retrieve the diff of files in the
198      * Central Dogma repository.
199      * Call {@link DiffFilesRequest#get(Revision, Revision)} to perform the same operation as
200      * {@link CentralDogma#getDiff(String, String, Revision, Revision, PathPattern)}.
201      */
202     public DiffFilesRequest diff(PathPattern pathPattern) {
203         requireNonNull(pathPattern, "pathPattern");
204         return new DiffFilesRequest(this, pathPattern);
205     }
206 
207     /**
208      * Returns a new {@link PreviewDiffRequest} that is used to retrieve the preview diff of files in the
209      * Central Dogma repository.
210      * Call {@link PreviewDiffRequest#get(Revision)} to perform the same operation as
211      * {@link CentralDogma#getPreviewDiffs(String, String, Revision, Iterable)}.
212      */
213     public PreviewDiffRequest diff(Change<?>... changes) {
214         requireNonNull(changes, "changes");
215         return new PreviewDiffRequest(this, ImmutableList.copyOf(changes));
216     }
217 
218     /**
219      * Returns a new {@link PreviewDiffRequest} that is used to retrieve the preview diff of files in the
220      * Central Dogma repository.
221      * Call {@link PreviewDiffRequest#get(Revision)} to perform the same operation as
222      * {@link CentralDogma#getPreviewDiffs(String, String, Revision, Iterable)}.
223      */
224     public PreviewDiffRequest diff(Iterable<? extends Change<?>> changes) {
225         requireNonNull(changes, "changes");
226         return new PreviewDiffRequest(this, changes);
227     }
228 
229     /**
230      * Returns a new {@link CommitRequest} that is used to push the {@link Change}s to the
231      * Central Dogma repository.
232      * Call {@link CommitRequest#push(Revision)} to perform the same operation as
233      * {@link CentralDogma#push(String, String, Revision, String, String, Markup, Iterable)}.
234      */
235     public CommitRequest commit(String summary, Change<?>... changes) {
236         requireNonNull(changes, "changes");
237         return commit(summary, ImmutableList.copyOf(changes));
238     }
239 
240     /**
241      * Returns a new {@link CommitRequest} that is used to push the {@link Change}s to the
242      * Central Dogma repository.
243      * Call {@link CommitRequest#push(Revision)} to perform the same operation as
244      * {@link CentralDogma#push(String, String, Revision, String, String, Markup, Iterable)}.
245      */
246     public CommitRequest commit(String summary, Iterable<? extends Change<?>> changes) {
247         requireNonNull(summary, "summary");
248         requireNonNull(changes, "changes");
249         return new CommitRequest(this, summary, changes);
250     }
251 
252     /**
253      * Returns a new {@link WatchRequest} that is used to watch the file in the
254      * Central Dogma repository.
255      * Call {@link WatchRequest#start(Revision)} to perform the same operation as
256      * {@link CentralDogma#watchFile(String, String, Revision, Query, long, boolean)}.
257      */
258     public WatchRequest<?> watch(String path) {
259         requireNonNull(path, "path");
260         return watch(Query.of(QueryType.IDENTITY, path));
261     }
262 
263     /**
264      * Returns a new {@link WatchRequest} that is used to watch the file in the
265      * Central Dogma repository.
266      * Call {@link WatchRequest#start(Revision)} to perform the same operation as
267      * {@link CentralDogma#watchFile(String, String, Revision, Query, long, boolean)}.
268      */
269     public <T> WatchRequest<T> watch(Query<T> query) {
270         requireNonNull(query, "query");
271         return new WatchRequest<>(this, query);
272     }
273 
274     /**
275      * Returns a new {@link WatchFilesRequest} that is used to watch the files in the
276      * Central Dogma repository.
277      * Call {@link WatchFilesRequest#start(Revision)} to perform the same operation as
278      * {@link CentralDogma#watchRepository(String, String, Revision, PathPattern, long, boolean)}.
279      */
280     public WatchFilesRequest watch(PathPattern pathPattern) {
281         requireNonNull(pathPattern, "pathPattern");
282         return new WatchFilesRequest(this, pathPattern);
283     }
284 
285     /**
286      * Returns a new {@link WatcherRequest} that is used to create a {@link Watcher}.
287      */
288     public <T> WatcherRequest<T> watcher(Query<T> query) {
289         requireNonNull(query, "query");
290         return new WatcherRequest<>(this, query, blockingTaskExecutor, meterRegistry);
291     }
292 
293     /**
294      * Returns a new {@link WatcherRequest} that is used to create a {@link Watcher}.
295      */
296     public WatcherRequest<Revision> watcher(PathPattern pathPattern) {
297         requireNonNull(pathPattern, "pathPattern");
298         return new WatcherRequest<>(this, pathPattern, blockingTaskExecutor, meterRegistry);
299     }
300 
301     @Override
302     public boolean equals(Object o) {
303         if (this == o) {
304             return true;
305         }
306         if (!(o instanceof CentralDogmaRepository)) {
307             return false;
308         }
309         final CentralDogmaRepository that = (CentralDogmaRepository) o;
310         return centralDogma == that.centralDogma &&
311                projectName.equals(that.projectName) && repositoryName.equals(that.repositoryName) &&
312                blockingTaskExecutor == that.blockingTaskExecutor;
313     }
314 
315     @Override
316     public int hashCode() {
317         return Objects.hash(centralDogma, projectName, repositoryName, blockingTaskExecutor);
318     }
319 
320     @Override
321     public String toString() {
322         return MoreObjects.toStringHelper(this)
323                           .add("centralDogma", centralDogma)
324                           .add("projectName", projectName)
325                           .add("repositoryName", repositoryName)
326                           .add("blockingTaskExecutor", blockingTaskExecutor)
327                           .toString();
328     }
329 }