private void logWebserviceInvocation(WebserviceInvocation wi, Date invocationTime) {
    StringBuilder sql =
        new StringBuilder(
            "delete from library.webservice_history where calltype_id = "
                + wi.getCallType().getDatabaseId());

    Integer artistId = null,
        trackId = null,
        albumId = null,
        userId = null,
        groupId = null,
        tagId = null;
    if (wi.getTrack() != null) {
      sql.append(" and track_id = " + (trackId = musicDao.getTrackId(wi.getTrack())));
    } else if (wi.getAlbum() != null) {
      sql.append(" and album_id = " + (albumId = musicDao.getAlbumId(wi.getAlbum())));
    } else if (wi.getArtist() != null) {
      sql.append(" and artist_id = " + (artistId = musicDao.getArtistId(wi.getArtist())));
    } else if (wi.getUser() != null) {
      sql.append(
          " and lastfmuser_id = "
              + (userId = lastFmDao.getLastFmUserId(wi.getUser().getLastFmUsername())));
    } else if (wi.getGroup() != null) {
      sql.append(
          " and lastfmgroup_id = "
              + (groupId = lastFmDao.getLastFmGroupId(wi.getGroup().getName())));
    } else if (wi.getTag() != null) {
      sql.append(" and tag_id = " + (tagId = wi.getTag().getId()));
    }
    if (wi.getPage() != null) sql.append(" and page = " + wi.getPage());

    jdbcTemplate.update(sql.toString());
    jdbcTemplate.update(
        "insert into library.webservice_history"
            + " (artist_id, album_id, track_id, lastfmuser_id, lastfmgroup_id,"
            + " tag_id, calltype_id, page, invocation_time)"
            + " values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
        artistId,
        albumId,
        trackId,
        userId,
        groupId,
        tagId,
        wi.getCallType().getDatabaseId(),
        wi.getPage(),
        invocationTime);
  }
 /*
  * Implementation of DAO interface method to check if a certain invocation
  * would be allowed.
  *
  * Delegates decision to relevant method/query depending on type of invocation.
  */
 @Override
 public boolean isWebserviceInvocationAllowed(WebserviceInvocation wi) {
   if (wi.getTrack() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getTrack());
   } else if (wi.getAlbum() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getAlbum());
   } else if (wi.getArtist() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getArtist());
   } else if (wi.getUser() != null && wi.getPage() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getUser(), wi.getPage());
   } else if (wi.getUser() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getUser());
   } else if (wi.getGroup() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getGroup());
   } else if (wi.getTag() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getTag());
   } else if (wi.getPage() != null) {
     return isWebserviceInvocationAllowed(wi.getCallType(), wi.getPage());
   } else {
     // for compiler compliance, actually unreachable
     return false;
   }
 }