Coverage Summary for Class: CommonResourcePersister (com.acciente.oacc.sql.internal.persister)
Class | Class, % | Method, % | Line, % |
---|---|---|---|
CommonResourcePersister | 100% (1/ 1) | 90% (9/ 10) | 72% (85/ 118) |
1 /*
2 * Copyright 2009-2018, Acciente LLC
3 *
4 * Acciente LLC licenses this file to you under the
5 * Apache License, Version 2.0 (the "License"); you
6 * may not use this file except in compliance with the
7 * License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
14 * OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License.
17 */
18 package com.acciente.oacc.sql.internal.persister;
19
20 import com.acciente.oacc.Resource;
21 import com.acciente.oacc.Resources;
22 import com.acciente.oacc.sql.SQLProfile;
23 import com.acciente.oacc.sql.internal.persister.id.DomainId;
24 import com.acciente.oacc.sql.internal.persister.id.Id;
25 import com.acciente.oacc.sql.internal.persister.id.ResourceClassId;
26 import com.acciente.oacc.sql.internal.persister.id.ResourceId;
27
28 import java.io.Serializable;
29 import java.sql.SQLException;
30
31 public abstract class CommonResourcePersister extends Persister implements ResourcePersister, Serializable {
32 private static final long serialVersionUID = 1L;
33
34 protected static final String[] GENERATED_KEY_COLUMNS = new String[]{"ResourceId"};
35
36 protected final SQLProfile sqlProfile;
37 protected final SQLStrings sqlStrings;
38
39 public CommonResourcePersister(SQLProfile sqlProfile,
40 SQLStrings sqlStrings) {
41 this.sqlProfile = sqlProfile;
42 this.sqlStrings = sqlStrings;
43 }
44
45 @Override
46 public void verifyResourceExists(SQLConnection connection,
47 Resource resource) {
48 SQLStatement statement = null;
49
50 try {
51 SQLResult resultSet;
52
53 statement = connection.prepareStatement(sqlStrings.SQL_findInResource_ResourceId_BY_ResourceID);
54 statement.setResourceId(1, resource);
55 resultSet = statement.executeQuery();
56
57 // complain if we do not find the resource
58 if (!resultSet.next()) {
59 throw new IllegalArgumentException("Resource " + resource + " not found!");
60 }
61
62 // complain if we found more than one resource!
63 // (assuming the PK constraint is being enforced by the DB, currently do not see how this can happen)
64 if (resultSet.next()) {
65 throw new IllegalStateException("Resource reference " + resource + " maps to more than one resource!");
66 }
67 }
68 catch (SQLException e) {
69 throw new RuntimeException(e);
70 }
71 finally {
72 closeStatement(statement);
73 }
74 }
75
76 @Override
77 public Resource createResource(SQLConnection connection,
78 Id<ResourceClassId> resourceClassId,
79 Id<DomainId> resourceDomainId,
80 String externalId) {
81 SQLStatement statement = null;
82
83 try {
84 final Id<ResourceId> nextResourceId;
85
86 // pick the resource creation strategy based on if the database supports sequence generators
87 if (sqlProfile.isSequenceEnabled()) {
88 nextResourceId = getNextResourceId(connection);
89 if (nextResourceId == null) {
90 throw new IllegalStateException("could not retrieve next ResourceId from sequence");
91 }
92
93 statement = connection.prepareStatement(sqlStrings.SQL_createInResource_WITH_ResourceID_ResourceClassID_DomainID);
94 statement.setResourceId(1, nextResourceId);
95 statement.setResourceClassId(2, resourceClassId);
96 statement.setResourceDomainId(3, resourceDomainId);
97
98 assertOneRowInserted(statement.executeUpdate());
99 }
100 else {
101 statement = connection.prepareStatement(sqlStrings.SQL_createInResource_WITH_ResourceClassID_DomainID,
102 GENERATED_KEY_COLUMNS);
103 statement.setResourceClassId(1, resourceClassId);
104 statement.setResourceDomainId(2, resourceDomainId);
105
106 assertOneRowInserted(statement.executeUpdate());
107
108 final SQLResult generatedKeys = statement.getGeneratedKeys();
109
110 if (!generatedKeys.next()) {
111 throw new IllegalStateException("could not retrieve auto-generated ResourceId");
112 }
113
114 nextResourceId = generatedKeys.getNextResourceId(1);
115
116 if (nextResourceId == null) {
117 throw new IllegalStateException("could not retrieve auto-generated ResourceId");
118 }
119 generatedKeys.close();
120 }
121 closeStatement(statement);
122
123 // save the new resource's external id, if necessary, and return the new resource
124 if (externalId != null) {
125 return setExternalId(connection, nextResourceId, externalId);
126 }
127 else {
128 return Resources.getInstance(nextResourceId.getValue());
129 }
130 }
131 catch (SQLException e) {
132 throw new RuntimeException(e);
133 }
134 finally {
135 closeStatement(statement);
136 }
137 }
138
139 @Override
140 public Resource setExternalId(SQLConnection connection,
141 Id<ResourceId> resourceId,
142 String externalId) {
143 SQLStatement statement = null;
144
145 try {
146 // save the new resource's external id and return the new resource reference
147 statement = connection.prepareStatement(sqlStrings.SQL_createInResourceExternalId_WITH_ResourceID_ExternalID);
148 statement.setResourceId(1, resourceId);
149 statement.setString(2, externalId);
150
151 assertOneRowInserted(statement.executeUpdate());
152
153 return Resources.getInstance(resourceId.getValue(), externalId);
154 }
155 catch (SQLException e) {
156 throw new RuntimeException(e);
157 }
158 finally {
159 closeStatement(statement);
160 }
161 }
162
163 @Override
164 public void deleteResource(SQLConnection connection,
165 Resource resource) {
166 SQLStatement statement = null;
167
168 try {
169 // delete the resource's external id mapping, if exists
170 statement = connection.prepareStatement(sqlStrings.SQL_removeInResourceExternalId_BY_ResourceID);
171 statement.setResourceId(1, resource);
172 statement.executeUpdate();
173 closeStatement(statement);
174
175 // delete resource
176 statement = connection.prepareStatement(sqlStrings.SQL_removeInResource_BY_ResourceID);
177 statement.setResourceId(1, resource);
178
179 assertOneRowUpdated(statement.executeUpdate());
180 }
181 catch (SQLException e) {
182 throw new RuntimeException(e);
183 }
184 finally {
185 closeStatement(statement);
186 }
187 }
188
189 @Override
190 public Id<DomainId> getDomainIdByResource(SQLConnection connection,
191 Resource resource) {
192 SQLStatement statement = null;
193
194 try {
195 Id<DomainId> domainId = null;
196
197 statement = connection.prepareStatement(sqlStrings.SQL_findInResource_DomainID_BY_ResourceID);
198 statement.setResourceId(1, resource);
199 SQLResult resultSet = statement.executeQuery();
200
201 if (resultSet.next()) {
202 domainId = resultSet.getResourceDomainId("DomainId");
203 }
204
205 if (domainId == null) {
206 throw new IllegalArgumentException("Could not determine domain for resource: " + resource);
207 }
208
209 return domainId;
210 }
211 catch (SQLException e) {
212 throw new RuntimeException(e);
213 }
214 finally {
215 closeStatement(statement);
216 }
217 }
218
219 @Override
220 public Id<ResourceId> getNextResourceId(SQLConnection connection) {
221 SQLStatement statement = null;
222 Id<ResourceId> newResourceId = null;
223
224 try {
225 SQLResult resultSet;
226
227 statement = connection.prepareStatement(sqlStrings.SQL_nextResourceID);
228 resultSet = statement.executeQuery();
229
230 if (resultSet.next()) {
231 newResourceId = resultSet.getNextResourceId(1);
232 }
233
234 resultSet.close();
235
236 return newResourceId;
237 }
238 catch (SQLException e) {
239 throw new RuntimeException(e);
240 }
241 finally {
242 closeStatement(statement);
243 }
244 }
245
246 @Override
247 public abstract boolean isDomainEmpty(SQLConnection connection, Id<DomainId> resourceDomainId);
248
249 @Override
250 public Resource resolveResourceByExternalId(SQLConnection connection,
251 String externalId) {
252 SQLStatement statement = null;
253
254 try {
255 SQLResult resultSet;
256
257 statement = connection.prepareStatement(sqlStrings.SQL_findInResourceExternalId_ResourceId_ExternalId_BY_ExternalID);
258 statement.setString(1, externalId);
259 resultSet = statement.executeQuery();
260
261 if (!resultSet.next()) {
262 return null;
263 }
264
265 final Resource resolvedResourceId = resultSet.getResource("ResourceId", "ExternalId");
266
267 // complain if we found more than one resource - external ids are supposed to be globally unique
268 if (resultSet.next()) {
269 throw new IllegalStateException("External id " + externalId + " maps to more than one resource!");
270 }
271
272 return resolvedResourceId;
273 }
274 catch (SQLException e) {
275 throw new RuntimeException(e);
276 }
277 finally {
278 closeStatement(statement);
279 }
280 }
281
282 @Override
283 public Resource resolveResourceByResourceId(SQLConnection connection,
284 Resource resource) {
285 SQLStatement statement = null;
286
287 try {
288 SQLResult resultSet;
289
290 statement = connection.prepareStatement(sqlStrings.SQL_findInResource_ResourceId_ExternalId_BY_ResourceID);
291 statement.setResourceId(1, resource);
292 resultSet = statement.executeQuery();
293
294 // complain if we do not find the resource
295 if (!resultSet.next()) {
296 return null;
297 }
298
299 Resource resolvedResource = resultSet.getResource("ResourceId", "ExternalId");
300
301 // complain if we found more than one resource - external ids are supposed to be globally unique
302 if (resultSet.next()) {
303 throw new IllegalStateException("Resource " + resource + " maps to more than one resource!");
304 }
305
306 return resolvedResource;
307 }
308 catch (SQLException e) {
309 throw new RuntimeException(e);
310 }
311 finally {
312 closeStatement(statement);
313 }
314 }
315 }