Line data Source code
1 : // Copyright (C) 2013 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.api.changes; 16 : 17 : import static com.google.common.base.Preconditions.checkState; 18 : import static com.google.gerrit.server.api.ApiUtil.asRestApiException; 19 : import static java.util.Objects.requireNonNull; 20 : 21 : import com.google.common.base.Joiner; 22 : import com.google.common.collect.ImmutableList; 23 : import com.google.gerrit.entities.Change; 24 : import com.google.gerrit.extensions.api.changes.ChangeApi; 25 : import com.google.gerrit.extensions.api.changes.Changes; 26 : import com.google.gerrit.extensions.client.ListChangesOption; 27 : import com.google.gerrit.extensions.common.ChangeInfo; 28 : import com.google.gerrit.extensions.common.ChangeInput; 29 : import com.google.gerrit.extensions.registration.DynamicMap; 30 : import com.google.gerrit.extensions.restapi.IdString; 31 : import com.google.gerrit.extensions.restapi.RestApiException; 32 : import com.google.gerrit.extensions.restapi.TopLevelResource; 33 : import com.google.gerrit.extensions.restapi.Url; 34 : import com.google.gerrit.server.DynamicOptions; 35 : import com.google.gerrit.server.api.changes.ChangeApiImpl.DynamicOptionParser; 36 : import com.google.gerrit.server.restapi.change.ChangesCollection; 37 : import com.google.gerrit.server.restapi.change.CreateChange; 38 : import com.google.gerrit.server.restapi.change.QueryChanges; 39 : import com.google.inject.Inject; 40 : import com.google.inject.Injector; 41 : import com.google.inject.Provider; 42 : import com.google.inject.Singleton; 43 : import java.util.List; 44 : 45 : @Singleton 46 : class ChangesImpl implements Changes { 47 : private final ChangesCollection changes; 48 : private final ChangeApiImpl.Factory api; 49 : private final CreateChange createChange; 50 : private final DynamicOptionParser dynamicOptionParser; 51 : private final Provider<QueryChanges> queryProvider; 52 : private final Injector injector; 53 : private final DynamicMap<DynamicOptions.DynamicBean> dynamicBeans; 54 : 55 : @Inject 56 : ChangesImpl( 57 : ChangesCollection changes, 58 : ChangeApiImpl.Factory api, 59 : CreateChange createChange, 60 : DynamicOptionParser dynamicOptionParser, 61 : Provider<QueryChanges> queryProvider, 62 : Injector injector, 63 149 : DynamicMap<DynamicOptions.DynamicBean> dynamicBeans) { 64 149 : this.changes = changes; 65 149 : this.api = api; 66 149 : this.createChange = createChange; 67 149 : this.dynamicOptionParser = dynamicOptionParser; 68 149 : this.queryProvider = queryProvider; 69 149 : this.injector = injector; 70 149 : this.dynamicBeans = dynamicBeans; 71 149 : } 72 : 73 : @Override 74 : public ChangeApi id(int id) throws RestApiException { 75 51 : return id(String.valueOf(id)); 76 : } 77 : 78 : @Override 79 : public ChangeApi id(String project, String branch, String id) throws RestApiException { 80 1 : return id( 81 1 : Joiner.on('~') 82 1 : .join(ImmutableList.of(Url.encode(project), Url.encode(branch), Url.encode(id)))); 83 : } 84 : 85 : @Override 86 : public ChangeApi id(String id) throws RestApiException { 87 : try { 88 89 : return api.create(changes.parse(TopLevelResource.INSTANCE, IdString.fromUrl(id))); 89 5 : } catch (Exception e) { 90 5 : throw asRestApiException("Cannot parse change", e); 91 : } 92 : } 93 : 94 : @Override 95 : public ChangeApi id(String project, int id) throws RestApiException { 96 2 : return id( 97 2 : Joiner.on('~').join(ImmutableList.of(Url.encode(project), Url.encode(String.valueOf(id))))); 98 : } 99 : 100 : @Override 101 : public ChangeApi create(ChangeInput in) throws RestApiException { 102 : try { 103 31 : ChangeInfo out = createChange.apply(TopLevelResource.INSTANCE, in).value(); 104 31 : return api.create(changes.parse(Change.id(out._number))); 105 4 : } catch (Exception e) { 106 4 : throw asRestApiException("Cannot create change", e); 107 : } 108 : } 109 : 110 : @Override 111 : public ChangeInfo createAsInfo(ChangeInput in) throws RestApiException { 112 : try { 113 1 : return createChange.apply(TopLevelResource.INSTANCE, in).value(); 114 0 : } catch (Exception e) { 115 0 : throw asRestApiException("Cannot create change", e); 116 : } 117 : } 118 : 119 : @Override 120 : public QueryRequest query() { 121 22 : return new QueryRequest() { 122 : @Override 123 : public List<ChangeInfo> get() throws RestApiException { 124 22 : return ChangesImpl.this.get(this); 125 : } 126 : }; 127 : } 128 : 129 : @Override 130 : public QueryRequest query(String query) { 131 21 : return query().withQuery(query); 132 : } 133 : 134 : private List<ChangeInfo> get(QueryRequest q) throws RestApiException { 135 22 : try (DynamicOptions dynamicOptions = new DynamicOptions(injector, dynamicBeans)) { 136 22 : QueryChanges qc = queryProvider.get(); 137 22 : if (q.getQuery() != null) { 138 21 : qc.addQuery(q.getQuery()); 139 : } 140 22 : qc.setLimit(q.getLimit()); 141 22 : qc.setStart(q.getStart()); 142 22 : qc.setNoLimit(q.getNoLimit()); 143 22 : for (ListChangesOption option : q.getOptions()) { 144 12 : qc.addOption(option); 145 12 : } 146 22 : dynamicOptionParser.parseDynamicOptions(qc, q.getPluginOptions(), dynamicOptions); 147 : 148 : try { 149 22 : List<?> result = qc.apply(TopLevelResource.INSTANCE).value(); 150 22 : if (result.isEmpty()) { 151 16 : return ImmutableList.of(); 152 : } 153 : 154 : // Check type safety of result; the extension API should be safer than the 155 : // REST API in this case, since it's intended to be used in Java. 156 22 : Object first = requireNonNull(result.iterator().next()); 157 22 : checkState(first instanceof ChangeInfo); 158 : @SuppressWarnings("unchecked") 159 22 : List<ChangeInfo> infos = (List<ChangeInfo>) result; 160 : 161 22 : return ImmutableList.copyOf(infos); 162 6 : } catch (Exception e) { 163 6 : throw asRestApiException("Cannot query changes", e); 164 : } 165 16 : } 166 : } 167 : }