+ /**
+ * Loads the properties for the given track derivatives.
+ *
+ * @param trackDerivatives
+ * The track derivatives to load the properties for
+ * @return The track derivatives with their properties loaded
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public List<TrackDerivative> loadTrackDerivativeProperties(List<TrackDerivative> trackDerivatives) throws DatabaseException {
+ for (TrackDerivative trackDerivative : trackDerivatives) {
+ loadTrackDerivativeProperties(trackDerivative);
+ }
+ return trackDerivatives;
+ }
+
+ /**
+ * Saves the given track derivative. As a track derivative does not have any
+ * attributes of its own only its properties are saved.
+ *
+ * @param trackDerivative
+ * The track derivative to save
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public void saveTrackDerivate(TrackDerivative trackDerivative) throws DatabaseException {
+ saveProperties(trackDerivative.getProperties(), "TRACK_DERIVATIVE_PROPERTIES", "TRACK_DERIVATIVE", trackDerivative.getId());
+ }
+
+ /**
+ * Removes the given track derivative and all its properties from the
+ * database.
+ *
+ * @param trackDerivative
+ * The track derivative to remove
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public void removeTrackDerivative(TrackDerivative trackDerivative) throws DatabaseException {
+ Query query = new Query(Type.DELETE, "TRACK_DERIVATIVES");
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_DERIVATIVES.ID", new StringParameter(trackDerivative.getId()))));
+ database.update(query);
+ /* remove the properties. */
+ saveProperties(new Properties().set("dirty", "true").removeAll(), "TRACK_DERIVATIVE_PROPERTIES", "TRACK_DERIVATIVE", trackDerivative.getId());
+ }
+
+ /**
+ * Returns all groups the artist with the given ID belongs to.
+ *
+ * @param artistId
+ * The ID of the artist
+ * @return All groups the artist belongs to
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Collection<Group> getGroupsByArtist(String artistId) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "GROUPS");
+ query.addField(new Field("GROUPS.*"));
+ query.addJoin(new Join(JoinType.INNER, "GROUP_ARTISTS", new Field("GROUPS.ID"), new Field("GROUP_ARTISTS.GROUP_")));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("GROUP_ARTISTS.ARTIST", new StringParameter(artistId))));
+ return database.getMultiple(query, groupCreator);
+ }
+
+ /**
+ * Returns all styles for the track with the given ID.
+ *
+ * @param trackId
+ * The ID of the track
+ * @return All styles for the given track
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Collection<Style> getStylesByTrack(String trackId) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "STYLES");
+ query.addField(new Field("STYLES.*"));
+ query.addJoin(new Join(JoinType.INNER, "TRACK_STYLES", new Field("STYLES.ID"), new Field("TRACK_STYLES.STYLE")));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_STYLES.TRACK", new StringParameter(trackId))));
+ return database.getMultiple(query, styleCreator);
+ }
+
+ /**
+ * Returns the user with the given name.
+ *
+ * @param username
+ * The name of the user
+ * @return The user, or {@code null} if the user does not exist
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public User getUserByName(String username) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "USERS");
+ query.addField(new Field("USERS.*"));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("USERS.NAME", new StringParameter(username))));
+ return database.getSingle(query, userCreator);
+ }
+
+ /**
+ * Returns the user connected with the given OpenID.
+ *
+ * @param openId
+ * The OpenID to find the user for
+ * @return The user connected with the given OpenID, or {@code null} if
+ * there is no such user
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public User getUserByOpenId(String openId) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "USERS");
+ query.addField(new Field("USERS.*"));
+ query.addJoin(new Join(JoinType.INNER, "USER_OPENIDS", new Field("USER_OPENIDS.USER"), new Field("USERS.ID")));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("USER_OPENIDS.OPENID", new StringParameter(openId))));
+ return database.getSingle(query, userCreator);
+ }
+
+ /**
+ * Returns all OpenIDs connected with the user with the given ID.
+ *
+ * @param userId
+ * The ID of the user
+ * @return All OpenIDs connected with the given user
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Collection<String> getOpenIdsByUser(String userId) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "USER_OPENIDS");
+ query.addField(new Field("USER_OPENIDS.*"));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("USER_OPENIDS.USER", new StringParameter(userId))));
+ return database.getMultiple(query, new StringCreator("USER_OPENIDS.OPENID"));
+ }
+
+ //
+ // PRIVATE METHODS
+ //
+
+ /**
+ * Loads the properties for the given object.
+ *
+ * @param <T>
+ * The type of the object
+ * @param object
+ * The object
+ * @param table
+ * The table to load the properties from
+ * @param type
+ * The type of the object (“ARTIST,” “TRACK,” etc.)
+ * @return The object with its properties loaded
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ private <T extends Base> T loadProperties(final T object, final String table, String type) throws DatabaseException {
+ Query query = new Query(Type.SELECT, table);
+ query.addField(new Field(table + ".PROPERTY"));
+ query.addField(new Field(table + ".VALUE"));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField(type, new StringParameter(object.getId()))));
+ database.process(query, new ResultProcessor() {
+
+ @Override
+ public void processResult(ResultSet resultSet) throws SQLException {
+ if (resultSet.isFirst()) {
+ object.getProperties().removeAll();
+ }
+ object.getProperties().set(resultSet.getString(table + ".PROPERTY"), resultSet.getString(table + ".VALUE"));
+ }
+
+ });
+ return object;
+ }
+
+ /**
+ * {@link Artist} implementation that retrieves some attributes (such as
+ * {@link #getGroups()}, and {@link #getTracks()}) from the
+ * {@link DataManager} on demand.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+ private class LazyArtist extends DefaultArtist {
+
+ /** Memoizer for the tracks by this artist. */
+ private final Memoizer<Void> tracksMemoizer = new Memoizer<Void>(new Callable<Void>() {
+
+ @Override
+ public Void call() throws DatabaseException {
+ if (!hasValue("tracks")) {
+ getValue("tracks", Collection.class).set(getTracksByArtist(getId()));
+ }
+ return null;
+ }
+ });