1   /*
2    * Copyright 2019 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  
17  package com.linecorp.centraldogma.client;
18  
19  import static com.linecorp.centraldogma.internal.PathPatternUtil.toPathPattern;
20  import static java.util.Objects.requireNonNull;
21  
22  import java.util.List;
23  import java.util.concurrent.CompletableFuture;
24  import java.util.concurrent.Executor;
25  import java.util.concurrent.ScheduledExecutorService;
26  import java.util.function.Function;
27  
28  import com.linecorp.centraldogma.common.Author;
29  import com.linecorp.centraldogma.common.Change;
30  import com.linecorp.centraldogma.common.Commit;
31  import com.linecorp.centraldogma.common.Entry;
32  import com.linecorp.centraldogma.common.Markup;
33  import com.linecorp.centraldogma.common.MergeSource;
34  import com.linecorp.centraldogma.common.MergedEntry;
35  import com.linecorp.centraldogma.common.PushResult;
36  import com.linecorp.centraldogma.common.Query;
37  import com.linecorp.centraldogma.common.Revision;
38  
39  /**
40   * A skeletal {@link CentralDogma} implementation.
41   */
42  public abstract class AbstractCentralDogma implements CentralDogma {
43  
44      private final ScheduledExecutorService blockingTaskExecutor;
45  
46      /**
47       * Creates a new instance.
48       *
49       * @param blockingTaskExecutor the {@link ScheduledExecutorService} which will be used for scheduling the
50       *                             tasks related with automatic retries and invoking the callbacks for
51       *                             watched changes.
52       */
53      protected AbstractCentralDogma(ScheduledExecutorService blockingTaskExecutor) {
54          this.blockingTaskExecutor = requireNonNull(blockingTaskExecutor, "blockingTaskExecutor");
55      }
56  
57      /**
58       * Returns the {@link ScheduledExecutorService} which is used for scheduling the tasks related with
59       * automatic retries and invoking the callbacks for watched changes.
60       */
61      protected final ScheduledExecutorService executor() {
62          return blockingTaskExecutor;
63      }
64  
65      @Override
66      public CentralDogmaRepository forRepo(String projectName, String repositoryName) {
67          requireNonNull(projectName, "projectName");
68          requireNonNull(repositoryName, "repositoryName");
69          return new CentralDogmaRepository(this, projectName, repositoryName, blockingTaskExecutor);
70      }
71  
72      @Override
73      public final CompletableFuture<Entry<?>> getFile(
74              String projectName, String repositoryName, Revision revision, String path) {
75          return CentralDogma.super.getFile(projectName, repositoryName, revision, path);
76      }
77  
78      @Override
79      public final CompletableFuture<MergedEntry<?>> mergeFiles(
80              String projectName, String repositoryName, Revision revision, MergeSource... mergeSources) {
81          return CentralDogma.super.mergeFiles(projectName, repositoryName, revision, mergeSources);
82      }
83  
84      @Override
85      public final CompletableFuture<MergedEntry<?>> mergeFiles(
86              String projectName, String repositoryName, Revision revision, Iterable<MergeSource> mergeSources) {
87          return CentralDogma.super.mergeFiles(projectName, repositoryName, revision, mergeSources);
88      }
89  
90      @Override
91      public final CompletableFuture<List<Commit>> getHistory(
92              String projectName, String repositoryName, Revision from, Revision to) {
93          return CentralDogma.super.getHistory(projectName, repositoryName, from, to);
94      }
95  
96      @Override
97      public final CompletableFuture<Change<?>> getDiff(
98              String projectName, String repositoryName, Revision from, Revision to, String path) {
99          return CentralDogma.super.getDiff(projectName, repositoryName, from, to, path);
100     }
101 
102     @Override
103     public final CompletableFuture<List<Change<?>>> getPreviewDiffs(
104             String projectName, String repositoryName, Revision baseRevision, Change<?>... changes) {
105         return CentralDogma.super.getPreviewDiffs(projectName, repositoryName, baseRevision, changes);
106     }
107 
108     @Override
109     public final CompletableFuture<PushResult> push(
110             String projectName, String repositoryName, Revision baseRevision,
111             String summary, Change<?>... changes) {
112         return CentralDogma.super.push(projectName, repositoryName, baseRevision, summary, changes);
113     }
114 
115     @Override
116     public final CompletableFuture<PushResult> push(
117             String projectName, String repositoryName, Revision baseRevision,
118             String summary, Iterable<? extends Change<?>> changes) {
119         return CentralDogma.super.push(projectName, repositoryName, baseRevision, summary, changes);
120     }
121 
122     @Override
123     public final CompletableFuture<PushResult> push(
124             String projectName, String repositoryName, Revision baseRevision,
125             String summary, String detail, Markup markup, Change<?>... changes) {
126         return CentralDogma.super.push(projectName, repositoryName, baseRevision,
127                                        summary, detail, markup, changes);
128     }
129 
130     @Override
131     public final CompletableFuture<PushResult> push(
132             String projectName, String repositoryName, Revision baseRevision,
133             Author author, String summary, Change<?>... changes) {
134         return CentralDogma.super.push(projectName, repositoryName, baseRevision, author, summary, changes);
135     }
136 
137     @Override
138     public final CompletableFuture<PushResult> push(
139             String projectName, String repositoryName, Revision baseRevision,
140             Author author, String summary, Iterable<? extends Change<?>> changes) {
141         return CentralDogma.super.push(projectName, repositoryName, baseRevision, author, summary, changes);
142     }
143 
144     @Override
145     public final CompletableFuture<PushResult> push(
146             String projectName, String repositoryName, Revision baseRevision,
147             Author author, String summary, String detail, Markup markup, Change<?>... changes) {
148         return CentralDogma.super.push(projectName, repositoryName, baseRevision,
149                                        author, summary, detail, markup, changes);
150     }
151 
152     @Override
153     public <T, U> Watcher<U> fileWatcher(
154             String projectName, String repositoryName, Query<T> query,
155             Function<? super T, ? extends U> function) {
156         return fileWatcher(projectName, repositoryName, query, function, blockingTaskExecutor);
157     }
158 
159     @Override
160     public <T, U> Watcher<U> fileWatcher(String projectName, String repositoryName, Query<T> query,
161                                          Function<? super T, ? extends U> function, Executor executor) {
162         //noinspection unchecked
163         return (Watcher<U>) forRepo(projectName, repositoryName).watcher(query)
164                                                                 .map(function)
165                                                                 .mapperExecutor(executor)
166                                                                 .start();
167     }
168 
169     @Override
170     public <T> Watcher<T> repositoryWatcher(
171             String projectName, String repositoryName, String pathPattern,
172             Function<Revision, ? extends T> function) {
173         return repositoryWatcher(projectName, repositoryName, pathPattern, function, blockingTaskExecutor);
174     }
175 
176     @Override
177     public <T> Watcher<T> repositoryWatcher(String projectName, String repositoryName, String pathPattern,
178                                             Function<Revision, ? extends T> function, Executor executor) {
179         //noinspection unchecked
180         return (Watcher<T>) forRepo(projectName, repositoryName).watcher(toPathPattern(pathPattern))
181                                                                 .map(function)
182                                                                 .mapperExecutor(executor)
183                                                                 .start();
184     }
185 
186     /**
187      * Normalizes the specified {@link Revision} only if it is a relative revision.
188      *
189      * @return the absolute {@link Revision}
190      */
191     protected final CompletableFuture<Revision> maybeNormalizeRevision(
192             String projectName, String repositoryName, Revision revision) {
193 
194         if (revision.isRelative()) {
195             return normalizeRevision(projectName, repositoryName, revision);
196         } else {
197             return CompletableFuture.completedFuture(revision);
198         }
199     }
200 }