+ query.addField(new Field("TRACK_RELATIONS.*"));
+ query.addJoin(new Join(JoinType.INNER, "TRACK_RELATIONS", new Field("TRACK_RELATIONS.TRACK"), new Field("TRACK_RELATIONS.RELATED_TRACK")));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_RELATIONS.TRACK", new StringParameter(trackId))));
+ final Map<Relationship, Collection<Track>> relatedTracks = new EnumMap<Relationship, Collection<Track>>(Relationship.class);
+ database.process(query, new ResultProcessor() {
+
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void processResult(ResultSet resultSet) throws SQLException {
+ Track track = trackCreator.createObject(resultSet);
+ Relationship relationship = Relationship.valueOf(resultSet.getString("TRACK_RELATIONS.RELATIONSHIP"));
+ if (!relatedTracks.containsKey(relationship)) {
+ relatedTracks.put(relationship, new HashSet<Track>());
+ }
+ relatedTracks.get(relationship).add(track);
+ }
+ });
+ return relatedTracks;
+ }
+
+ /**
+ * Returns the track with the given ID.
+ *
+ * @param id
+ * The ID of the track
+ * @return The track with the given ID, or {@code null} if there is no such
+ * track
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Track getTrackById(String id) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "TRACKS");
+ query.addField(new Field("TRACKS.*"));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACKS.ID", new StringParameter(id))));
+ return loadTrackProperties(database.getSingle(query, trackCreator));
+ }
+
+ /**
+ * Returns the track that contains the derivative with the given ID.
+ *
+ * @param id
+ * The ID of the track derivative
+ * @return The track the derivative belongs to, or {@code null} if there is
+ * no such track
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Track getTrackByDerivativeId(String id) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "TRACKS");
+ query.addField(new Field("TRACKS.*"));
+ query.addJoin(new Join(JoinType.INNER, "TRACK_DERIVATIVES", new Field("TRACK_DERIVATIVES.TRACK"), new Field("TRACKS.ID")));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_DERIVATIVES.ID", new StringParameter(id))));
+ return loadTrackProperties(database.getSingle(query, trackCreator));
+ }
+
+ /**
+ * Returns all tracks by the artist with the given ID.
+ *
+ * @param artistId
+ * The ID of the artist
+ * @return All tracks by the given artist
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Collection<Track> getTracksByArtist(String artistId) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "TRACKS");
+ query.addField(new Field("TRACKS.*"));
+ query.addJoin(new Join(JoinType.INNER, "TRACK_ARTISTS", new Field("TRACKS.ID"), new Field("TRACK_ARTISTS.TRACK")));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_ARTISTS.ARTIST", new StringParameter(artistId))));
+ return loadTrackProperties(database.getMultiple(query, trackCreator));
+ }
+
+ /**
+ * Loads the properties for the given track.
+ *
+ * @param track
+ * The track for which to load the properties
+ * @return The track with the properties loaded
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Track loadTrackProperties(Track track) throws DatabaseException {
+ return loadProperties(track, "TRACK_PROPERTIES", "TRACK");
+ }
+
+ /**
+ * Loads the properties for the given tracks.
+ *
+ * @param tracks
+ * The tracks for which to load the properties
+ * @return The tracks with the properties loaded
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public List<Track> loadTrackProperties(List<Track> tracks) throws DatabaseException {
+ for (Track track : tracks) {
+ loadTrackProperties(track);
+ }
+ return tracks;
+ }
+
+ /**
+ * Creates a new track with the given name.
+ *
+ * @param name
+ * The name of the track
+ * @return The created track
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Track createTrack(String name) throws DatabaseException {
+ Query query = new Query(Type.INSERT, "TRACKS");
+ String id = UUID.randomUUID().toString();
+ query.addValueField(new ValueField("ID", new StringParameter(id)));
+ query.addValueField(new ValueField("NAME", new StringParameter(name)));
+ database.insert(query);
+ return getTrackById(id);
+ }
+
+ /**
+ * Saves the given track. This also saves all relationships of the track.
+ *
+ * @param track
+ * The track to save
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public void saveTrack(Track track) throws DatabaseException {
+ Query query = new Query(Type.UPDATE, "TRACKS");
+ query.addValueField(new ValueField("TRACKS.NAME", new StringParameter(track.getName())));
+ query.addValueField(new ValueField("TRACKS.REMIX", new StringParameter(track.getRemix())));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACKS.ID", new StringParameter(track.getId()))));
+ database.update(query);
+ /* store artist information. */
+ track.getArtists(); /* prefetch artists. */
+ query = new Query(Type.DELETE, "TRACK_ARTISTS");
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_ARTISTS.TRACK", new StringParameter(track.getId()))));
+ database.update(query);
+ for (int index = 0; index < track.getArtists().size(); ++index) {
+ query = new Query(Type.INSERT, "TRACK_ARTISTS");
+ query.addValueField(new ValueField("TRACK_ARTISTS.TRACK", new StringParameter(track.getId())));
+ query.addValueField(new ValueField("TRACK_ARTISTS.ARTIST", new StringParameter(track.getArtists().get(index).getId())));
+ query.addValueField(new ValueField("TRACK_ARTISTS.DISPLAY_ORDER", new IntegerParameter(index + 1)));
+ database.insert(query);
+ }
+ /* store properties. */
+ saveProperties(track.getProperties(), "TRACK_PROPERTIES", "TRACK", track.getId());
+ }
+
+ /**
+ * Returns the derivative with the given ID.
+ *
+ * @param id
+ * The ID of the derivatives to load
+ * @return The derivative with the given ID
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public TrackDerivative getTrackDerivativeById(String id) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "TRACK_DERIVATIVES");
+ query.addField(new Field("TRACK_DERIVATIVES.*"));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_DERIVATIVES.ID", new StringParameter(id))));
+ return loadTrackDerivativeProperties(database.getSingle(query, trackDerivativeCreator));
+ }
+
+ /**
+ * Returns the derivatives for the given track.
+ *
+ * @param trackId
+ * The track ID to get the derivatives for
+ * @return The derivatives for the given track
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public Collection<TrackDerivative> getTrackDerivativesByTrack(String trackId) throws DatabaseException {
+ Query query = new Query(Type.SELECT, "TRACK_DERIVATIVES");
+ query.addField(new Field("TRACK_DERIVATIVES.*"));
+ query.addWhereClause(new ValueFieldWhereClause(new ValueField("TRACK_DERIVATIVES.TRACK", new StringParameter(trackId))));
+ return loadTrackDerivativeProperties(database.getMultiple(query, trackDerivativeCreator));
+ }
+
+ /**
+ * Creates a new derivative for the given track.
+ *
+ * @param track
+ * The track to create the derivative for
+ * @return The created derivative
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public TrackDerivative createTrackDerivative(Track track) throws DatabaseException {
+ Query query = new Query(Type.INSERT, "TRACK_DERIVATIVES");
+ String id = UUID.randomUUID().toString();
+ query.addValueField(new ValueField("TRACK_DERIVATIVES.ID", new StringParameter(id)));
+ query.addValueField(new ValueField("TRACK_DERIVATIVES.TRACK", new StringParameter(track.getId())));
+ database.insert(query);
+ return getTrackDerivativeById(id);
+ }
+
+ /**
+ * Loads the properties for the given track derivative.
+ *
+ * @param trackDerivative
+ * The track derivative to load the properties for
+ * @return The track derivative with its properties loaded
+ * @throws DatabaseException
+ * if a database error occurs
+ */
+ public TrackDerivative loadTrackDerivativeProperties(TrackDerivative trackDerivative) throws DatabaseException {
+ return loadProperties(trackDerivative, "TRACK_DERIVATIVE_PROPERTIES", "TRACK_DERIVATIVE");
+ }
+
+ /**
+ * 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");