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 }