package org.springframework.samples.petclinic.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.object.MappingSqlQuery;
import org.springframework.jdbc.object.SqlUpdate;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.samples.petclinic.Clinic;
import org.springframework.samples.petclinic.BaseEntity;
import org.springframework.samples.petclinic.Owner;
import org.springframework.samples.petclinic.Pet;
import org.springframework.samples.petclinic.PetType;
import org.springframework.samples.petclinic.Specialty;
import org.springframework.samples.petclinic.Vet;
import org.springframework.samples.petclinic.Visit;
import org.springframework.samples.petclinic.util.EntityUtils;
/**
* Base class for JDBC implementations of the Clinic interface.
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Rob Harrop
*/
public abstract class AbstractJdbcClinic extends JdbcDaoSupport implements Clinic, CachingClinic {
private VetsQuery vetsQuery;
private SpecialtiesQuery specialtiesQuery;
private VetSpecialtiesQuery vetSpecialtiesQuery;
private OwnersByNameQuery ownersByNameQuery;
private OwnerQuery ownerQuery;
private OwnerInsert ownerInsert;
private OwnerUpdate ownerUpdate;
private PetsByOwnerQuery petsByOwnerQuery;
private PetQuery petQuery;
private PetInsert petInsert;
private PetUpdate petUpdate;
private PetTypesQuery petTypesQuery;
private VisitsQuery visitsQuery;
private VisitInsert visitInsert;
private final List vets = new ArrayList();
protected void initDao() {
this.vetsQuery = new VetsQuery(getDataSource());
this.specialtiesQuery = new SpecialtiesQuery(getDataSource());
this.vetSpecialtiesQuery = new VetSpecialtiesQuery(getDataSource());
this.petTypesQuery = new PetTypesQuery(getDataSource());
this.ownersByNameQuery = new OwnersByNameQuery(getDataSource());
this.ownerQuery = new OwnerQuery(getDataSource());
this.ownerInsert = new OwnerInsert(getDataSource());
this.ownerUpdate = new OwnerUpdate(getDataSource());
this.petsByOwnerQuery = new PetsByOwnerQuery(getDataSource());
this.petQuery = new PetQuery(getDataSource());
this.petInsert = new PetInsert(getDataSource());
this.petUpdate = new PetUpdate(getDataSource());
this.visitsQuery = new VisitsQuery(getDataSource());
this.visitInsert = new VisitInsert(getDataSource());
}
public void refreshVetsCache() throws DataAccessException {
synchronized (this.vets) {
logger.info("Refreshing vets cache");
// Retrieve the list of all vets.
this.vets.clear();
this.vets.addAll(this.vetsQuery.execute());
// Retrieve the list of all possible specialties.
List specialties = this.specialtiesQuery.execute();
// Build each vet's list of specialties.
Iterator vi = this.vets.iterator();
while (vi.hasNext()) {
Vet vet = (Vet) vi.next();
List vetSpecialtiesIds = this.vetSpecialtiesQuery.execute(vet.getId().intValue());
Iterator vsi = vetSpecialtiesIds.iterator();
while (vsi.hasNext()) {
int specialtyId = ((Integer) vsi.next()).intValue();
Specialty specialty = (Specialty) EntityUtils.getById(specialties, Specialty.class, specialtyId);
vet.addSpecialty(specialty);
}
}
}
}
// START of Clinic implementation section *******************************
public Collection getVets() throws DataAccessException {
synchronized (this.vets) {
if (this.vets.isEmpty()) {
refreshVetsCache();
}
return this.vets;
}
}
public Collection getPetTypes() throws DataAccessException {
return this.petTypesQuery.execute();
}
/** Method loads owners plus pets and visits if not already loaded */
public Collection findOwners(String lastName) throws DataAccessException {
List owners = this.ownersByNameQuery.execute(lastName + "%");
loadOwnersPetsAndVisits(owners);
return owners;
}
/** Method loads an owner plus pets and visits if not already loaded */
public Owner loadOwner(int id) throws DataAccessException {
Owner owner = (Owner) this.ownerQuery.findObject(id);
if (owner == null) {
throw new ObjectRetrievalFailureException(Owner.class, new Integer(id));
}
loadPetsAndVisits(owner);
return owner;
}
public Pet loadPet(int id) throws DataAccessException {
JdbcPet pet = (JdbcPet) this.petQuery.findObject(id);
if (pet == null) {
throw new ObjectRetrievalFailureException(Pet.class, new Integer(id));
}
Owner owner = loadOwner(pet.getOwnerId());
owner.addPet(pet);
loadVisits(pet);
return pet;
}
public void storeOwner(Owner owner) throws DataAccessException {
if (owner.isNew()) {
this.ownerInsert.insert(owner);
}
else {
this.ownerUpdate.update(owner);
}
}
public void storePet(Pet pet) throws DataAccessException {
if (pet.isNew()) {
this.petInsert.insert(pet);
}
else {
this.petUpdate.update(pet);
}
}
public void storeVisit(Visit visit) throws DataAccessException {
if (visit.isNew()) {
this.visitInsert.insert(visit);
}
else {
throw new UnsupportedOperationException("Visit update not supported");
}
}
// END of Clinic implementation section *******************************
/**
* Method maps a List of BaseEntity objects keyed to their ids.
* @param list List containing BaseEntity objects
* @return Map containing BaseEntity objects
*/
protected final Map mapEntityList(List list) {
Map map = new HashMap();
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
BaseEntity entity = (BaseEntity) iterator.next();
map.put(entity.getId(), entity);
}
return map;
}
/**
* Method to retrieve the <code>Visit</code> data for a <code>Pet</code>.
*/
protected void loadVisits(JdbcPet pet) {
pet.setType((PetType) EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
List visits = this.visitsQuery.execute(pet.getId().intValue());
Iterator vi = visits.iterator();
while (vi.hasNext()) {
Visit visit = (Visit) vi.next();
pet.addVisit(visit);
}
}
/**
* Method to retrieve the <code>Pet</code> and <code>Visit</code>
* data for an <code>Owner</code>.
*/
protected void loadPetsAndVisits(Owner owner) {
List pets = this.petsByOwnerQuery.execute(owner.getId().intValue());
Iterator pi = pets.iterator();
while (pi.hasNext()) {
JdbcPet pet = (JdbcPet) pi.next();
owner.addPet(pet);
loadVisits(pet);
}
}
/**
* Method to retrieve a <code>List</code> of <code>Owner</code>s
* and their <code>Pet</code> and <code>Visit</code> data.
* @param owners <code>List</code>.
* @see #loadPetsAndVisits(Owner)
*/
protected void loadOwnersPetsAndVisits(List owners) {
Iterator oi = owners.iterator();
while (oi.hasNext()) {
Owner owner = (Owner) oi.next();
loadPetsAndVisits(owner);
}
}
/**
* Retrieve and set the identity for the given entity,
* assuming that the last executed insert affected that entity
* and generated an auto-increment value for it.
* @param entity the entity object to retrieved the id for
* @see #getIdentityQuery
*/
protected void retrieveIdentity(BaseEntity entity) {
entity.setId(new Integer(getJdbcTemplate().queryForInt(getIdentityQuery())));
}
/**
* Return the identity query for the particular database:
* a query that can be used to retrieve the id of a row
* that has just been inserted.
* @return the i