diff --git a/.idea/misc.xml b/.idea/misc.xml
index 690f4c6..4dc8c1e 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -4,7 +4,7 @@
-
+
\ No newline at end of file
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzArtist.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzArtist.java
index 4870ccc..7a04c5c 100644
--- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzArtist.java
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzArtist.java
@@ -12,7 +12,7 @@
import java.util.Locale;
-public class MusicBrainzArtist {
+public class MusicBrainzArtist extends MusicBrainzDataObject {
private String name;
private String dateOrganized; // May only be present for groups
private String birthDate; // May only be present for people
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzCDStub.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzCDStub.java
index bbe00e1..2f86cc5 100644
--- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzCDStub.java
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzCDStub.java
@@ -10,7 +10,7 @@
package com.CDPrintable.MusicBrainzResources;
-public class MusicBrainzCDStub {
+public class MusicBrainzCDStub extends MusicBrainzDataObject {
private String id;
private String title;
private String[] artists;
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzDataObject.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzDataObject.java
new file mode 100644
index 0000000..f968772
--- /dev/null
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzDataObject.java
@@ -0,0 +1,23 @@
+/*
+ * CDPrintable: A program that prints labels with track listings for your CD cases.
+ * Copyright (C) 2025 Alexander McLean
+ *
+ * This source code is licensed under the GNU General Public License v3.0
+ * found in the LICENSE file in the root directory of this source tree.
+ *
+ * This is an abstract data class for MusicBrainz data objects.
+ */
+
+package com.CDPrintable.MusicBrainzResources;
+
+public abstract class MusicBrainzDataObject {
+ private String id;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+}
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java
index eec8bd7..77a883e 100644
--- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java
@@ -11,6 +11,7 @@
package com.CDPrintable.MusicBrainzResources;
import com.CDPrintable.Constants;
+import com.CDPrintable.ProgramWindow;
import com.google.gson.*;
import java.util.ArrayList;
@@ -27,7 +28,7 @@ public class MusicBrainzJSONReader {
/*
* Creates a MusicBrainzJSONReader from a JSON string.
- * @param json The JSON string.
+ * @param JSON The JSON string.
* @throws IllegalArgumentException If the JSON is invalid.
*/
public MusicBrainzJSONReader(String json) throws IllegalArgumentException {
@@ -240,6 +241,49 @@ public MusicBrainzArtist[] getArtists() {
}, new MusicBrainzArtist[0]);
}
+ /**
+ * Gets track listing from the JSON from a discID.
+ */
+ public MusicBrainzTrack[] getTracks() {
+ return parseJsonArray("tracks", jsonObject -> {
+ String title = jsonHasAndIsNotNull(jsonObject, "title") ? jsonObject.get("title").getAsString() : null;
+ String artist = jsonHasAndIsNotNull(jsonObject, "artist") ? jsonObject.get("artist").getAsString() : null;
+ int length = jsonHasAndIsNotNull(jsonObject, "length") ? jsonObject.get("length").getAsInt() : -1;
+
+ return new MusicBrainzTrack(title, artist, length);
+ }, new MusicBrainzTrack[0]);
+ }
+
+ /**
+ * Gets track listing from a release.
+ * @return An array of MusicBrainzTrack objects.
+ */
+ public MusicBrainzTrack[] getReleaseTracks() {
+ List trackList = new ArrayList<>();
+
+ JsonArray mediaArray = json.getAsJsonArray("media");
+ for (JsonElement mediaElement : mediaArray) {
+ JsonObject mediaObject = mediaElement.getAsJsonObject(); // Cast each element to JsonObject
+ JsonArray trackArray = mediaObject.getAsJsonArray("tracks");
+ for (JsonElement trackElement : trackArray) {
+ JsonObject trackObject = trackElement.getAsJsonObject();
+ String title = jsonHasAndIsNotNull(trackObject, "title") ? trackObject.get("title").getAsString() : null;
+ int length = jsonHasAndIsNotNull(trackObject, "length") ? trackObject.get("length").getAsInt() : -1;
+ int trackNumber = -1;
+
+ if (trackObject.has("number")) {
+ trackNumber = trackObject.get("number").getAsInt();
+ } else if (trackObject.has("position")) {
+ trackNumber = trackObject.get("position").getAsInt();
+ }
+
+ trackList.add(new MusicBrainzTrack(title, null, length, trackNumber));
+ }
+ }
+
+ return trackList.toArray(new MusicBrainzTrack[0]);
+ }
+
/**
* Creates a table model from an array of items.
* @param items The array of items. Usually a MusicBrainzRelease, MusicBrainzCDStub, etc.
@@ -266,15 +310,15 @@ private DefaultTableModel createTableModel(Object[] items, String[] columnNames,
* @return The table model.
*/
public DefaultTableModel getReleasesAsTableModel(MusicBrainzRelease[] releaseArray) {
- String[] columnNames = {"Release Name", "Artist", "Track Count", "Date", ""};
+ String[] columnNames = {"Release Name", "Artist", "Track Count", "Date"};
return createTableModel(releaseArray, columnNames, item -> {
MusicBrainzRelease release = (MusicBrainzRelease) item;
+ ProgramWindow.addId(getOrDefault(release.getId()));
return new String[]{
getOrDefault(release.getTitle()),
getOrDefault(release.getArtistsAsString()),
getOrDefault(release.getTrackCount() != -1 ? String.valueOf(release.getTrackCount()) : null),
- getOrDefault(release.getDate()),
- ""
+ getOrDefault(release.getDate())
};
});
}
@@ -285,14 +329,14 @@ public DefaultTableModel getReleasesAsTableModel(MusicBrainzRelease[] releaseArr
* @return The table model.
*/
public DefaultTableModel getCDStubsAsTableModel(MusicBrainzCDStub[] cdStubArray) {
- String[] columnNames = {"Disc Name", "Artist", "Track Count", ""};
+ String[] columnNames = {"Disc Name", "Artist", "Track Count"};
return createTableModel(cdStubArray, columnNames, item -> {
MusicBrainzCDStub cdStub = (MusicBrainzCDStub) item;
+ ProgramWindow.addId(getOrDefault(cdStub.getId()));
return new String[]{
getOrDefault(cdStub.getTitle()),
getOrDefault(cdStub.getArtistsAsString()),
- getOrDefault(String.valueOf(cdStub.getTrackCount())),
- ""
+ getOrDefault(String.valueOf(cdStub.getTrackCount()))
};
});
}
@@ -303,9 +347,10 @@ public DefaultTableModel getCDStubsAsTableModel(MusicBrainzCDStub[] cdStubArray)
* @return The table model.
*/
public DefaultTableModel getArtistsAsTableModel(MusicBrainzArtist[] artistArray) {
- String[] columnNames = {"Name", "Date Organised", "Birthdate", "Sort Name", "Gender", "Type", "Disambiguation", "Life Span", "Country", ""};
+ String[] columnNames = {"Artist Name", "Date Organised", "Birthdate", "Sort Name", "Gender", "Type", "Disambiguation", "Life Span", "Country"};
return createTableModel(artistArray, columnNames, item -> {
MusicBrainzArtist artist = (MusicBrainzArtist) item;
+ ProgramWindow.addId(getOrDefault(artist.getId()));
return new String[] {
getOrDefault(artist.getName()),
getOrDefault(artist.getDateOrganized()),
@@ -315,12 +360,28 @@ public DefaultTableModel getArtistsAsTableModel(MusicBrainzArtist[] artistArray)
getOrDefault(artist.getType()),
getOrDefault(artist.getDisambiguation()),
getOrDefault(artist.getLifeSpan()),
- getOrDefault(artist.getCountry()),
- ""
+ getOrDefault(artist.getCountry())
};
});
}
+ /**
+ * Gets the tracks as a table model.
+ * @param trackArray The array of tracks.
+ */
+ public DefaultTableModel getTracksAsTableModel(MusicBrainzTrack[] trackArray) {
+ String[] columnNames = {"#", "Track Name", "Artist", "Length"};
+ return createTableModel(trackArray, columnNames, item -> {
+ MusicBrainzTrack track = (MusicBrainzTrack) item;
+ return new String[]{
+ getOrDefault(Integer.toString(track.getTrackNumber())),
+ getOrDefault(track.getTitle()),
+ getOrDefault(track.getArtist()),
+ getOrDefault(track.getLength())
+ };
+ });
+ }
+
/**
* Functional interface for extracting data from an item.
*/
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRelease.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRelease.java
index 128cec3..fcb4c35 100644
--- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRelease.java
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRelease.java
@@ -10,7 +10,7 @@
package com.CDPrintable.MusicBrainzResources;
-public class MusicBrainzRelease {
+public class MusicBrainzRelease extends MusicBrainzDataObject {
private String title;
private String[] artists;
private String date;
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRequest.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRequest.java
index f7edc54..b158b83 100644
--- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRequest.java
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzRequest.java
@@ -41,11 +41,7 @@ public MusicBrainzRequest(String queryType, String query, String otherParams) {
this.otherParams = otherParams;
}
- /**
- * Builds the request URL for the Musicbrainz API.
- * @return The request URL.
- */
- public String buildRequestURL() {
+ private StringBuilder startRequestBuild() {
StringBuilder url = new StringBuilder("https://musicbrainz.org/ws/2/");
switch (queryType) {
@@ -64,17 +60,51 @@ public String buildRequestURL() {
default:
throw new IllegalArgumentException("Invalid query type: " + queryType);
}
- url.append("?query=").append(query);
- url.append("&fmt=json");
+
+ return url;
+ }
+
+ private String endRequestBuild(StringBuilder url) {
+ if (!url.toString().contains("?")) {
+ url.append("?fmt=json");
+ } else {
+ url.append("&fmt=json");
+ }
+
if (otherParams != null) {
url.append(otherParams);
}
- return url.toString()
- .replace(" ", "%20")
+ return replaceAllIllegalChars(url.toString());
+ }
+
+ private String replaceAllIllegalChars(String str) {
+ return str.replace(" ", "%20")
.replace("\"", "%22");
}
+ /**
+ * Builds the request URL for the Musicbrainz API.
+ * @return The request URL.
+ */
+ public String buildRequestURL() {
+ StringBuilder url = startRequestBuild();
+ url.append("?query=").append(query);
+
+ return endRequestBuild(url);
+ }
+
+ /**
+ * Builds the request URL for the Musicbrainz API to get a track list.
+ * @return The request URL.
+ */
+ public String buildTrackListURL() {
+ StringBuilder url = startRequestBuild();
+ url.append("/").append(query).append("?inc=recordings");
+
+ return endRequestBuild(url);
+ }
+
/**
* Gets the query string.
* @return The query string.
diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzTrack.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzTrack.java
new file mode 100644
index 0000000..72b19bf
--- /dev/null
+++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzTrack.java
@@ -0,0 +1,68 @@
+/*
+ * CDPrintable: A program that prints labels with track listings for your CD cases.
+ * Copyright (C) 2025 Alexander McLean
+ *
+ * This source code is licensed under the GNU General Public License v3.0
+ * found in the LICENSE file in the root directory of this source tree.
+ *
+ * This class holds data for a track from the MusicBrainz API.
+ */
+
+package com.CDPrintable.MusicBrainzResources;
+
+public class MusicBrainzTrack extends MusicBrainzDataObject {
+ private String title;
+ private String artist;
+ private int length;
+ private int trackNumber;
+
+ public MusicBrainzTrack(String title, String artist, int length) {
+ this.title = title;
+ this.artist = artist;
+ this.length = length;
+ this.trackNumber = 0;
+ }
+
+ public MusicBrainzTrack(String title, String artist, int length, int trackNumber) {
+ this.title = title;
+ this.artist = artist;
+ this.length = length;
+ this.trackNumber = trackNumber;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getArtist() {
+ return artist;
+ }
+
+ public void setArtist(String artist) {
+ this.artist = artist;
+ }
+
+ public String getLength() {
+ int seconds = length / 1000;
+ int minutes = (seconds % 3600) / 60;
+ seconds = seconds % 60;
+
+ return String.format("%02d:%02d", minutes, seconds);
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ }
+
+ public int getTrackNumber() {
+ return trackNumber;
+ }
+
+ public void setTrackNumber(int trackNumber) {
+ this.trackNumber = trackNumber;
+ }
+}
diff --git a/src/main/java/com/CDPrintable/ProgramWindow.java b/src/main/java/com/CDPrintable/ProgramWindow.java
index fbb8f7c..6d56ab5 100644
--- a/src/main/java/com/CDPrintable/ProgramWindow.java
+++ b/src/main/java/com/CDPrintable/ProgramWindow.java
@@ -18,6 +18,12 @@
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Locale;
import java.util.Objects;
public class ProgramWindow {
@@ -25,6 +31,7 @@ public class ProgramWindow {
private JLabel fullUserAgentLabel = new JLabel();
private final JPanel cdSearchPanel = new JPanel();
private final JLabel searchStatusLabel = new JLabel("Status: Nothing's going on.");
+ private static final ArrayList idList = new ArrayList<>();
/**
* Creates a new ProgramWindow and sets up the GUI.
@@ -83,7 +90,17 @@ private JPanel searchPanel() {
trackListPanel.setBorder(BorderFactory.createTitledBorder("Search Results"));
// Search table set up
- JTable searchTable = new JTable(getCDStubModel());
+ JTable searchTable = new JTable(getTableModel("CDStub"));
+ searchTable.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ int row = searchTable.rowAtPoint(e.getPoint());
+ int column = searchTable.columnAtPoint(e.getPoint());
+ if (row != -1 && column != -1) {
+ clickSearch(row, column, searchTable);
+ }
+ }
+ });
JScrollPane trackListScrollPane = new JScrollPane(searchTable);
trackListPanel.add(searchStatusLabel, BorderLayout.NORTH);
trackListPanel.add(trackListScrollPane, BorderLayout.CENTER);
@@ -104,38 +121,51 @@ private JPanel searchPanel() {
if (searchTypeComboBox.getSelectedItem() == null) {
return;
}
- setSearchStatus("Preforming search...", "blue");
- if (searchTypeComboBox.getSelectedItem().equals("CDStub")) {
- Constants.THREAD_MANAGER.submit(() -> {
- MusicBrainzJSONReader reader = sendRequest("cdstub", searchField.getText());
-
- // Get CDStubs and set the table model
- MusicBrainzCDStub[] cdStubs = reader.getCDStubs();
- searchTable.setModel(reader.getCDStubsAsTableModel(cdStubs));
- setSearchStatus("All done!", "green");
- });
- } else if (searchTypeComboBox.getSelectedItem().equals("Artist")) {
- Constants.THREAD_MANAGER.submit(() -> {
- MusicBrainzJSONReader reader = sendRequest("artist", searchField.getText());
-
- // Get Artists and set the table model
- MusicBrainzArtist[] artists = reader.getArtists();
- searchTable.setModel(reader.getArtistsAsTableModel(artists));
- setSearchStatus("All done!", "green");
- });
- } else if (searchTypeComboBox.getSelectedItem().equals("Release")) {
- Constants.THREAD_MANAGER.submit(() -> {
- MusicBrainzJSONReader reader = sendRequest("release", searchField.getText());
-
- // Get Releases and set the table model
- MusicBrainzRelease[] releases = reader.getReleases();
- searchTable.setModel(reader.getReleasesAsTableModel(releases));
- setSearchStatus("All done!", "green");
- });
+
+ String selectedItem = searchTypeComboBox.getSelectedItem().toString();
+ if (selectedItem != null) {
+ searchTable.setModel(getTableModel(selectedItem));
} else {
- // how does this even happen?
- JOptionPane.showMessageDialog(panel, "Please select a search type.");
+ selectedItem = "";
}
+
+ setSearchStatus("Preforming search...", "blue");
+ clearIdList();
+ String finalSelectedItem = selectedItem;
+ Constants.THREAD_MANAGER.submit(() -> {
+ MusicBrainzJSONReader reader = sendRequest(finalSelectedItem.toLowerCase(Locale.ROOT), searchField.getText());
+ switch (finalSelectedItem) {
+ case "CDStub" -> {
+ // Get CDStubs and set the table model
+ MusicBrainzCDStub[] cdStubs = reader.getCDStubs();
+ for (MusicBrainzCDStub cdStub : cdStubs) {
+ addId(cdStub.getId());
+ }
+ setSearchStatus("All done!", "green");
+ searchTable.setModel(reader.getCDStubsAsTableModel(cdStubs));
+ }
+ case "Artist" -> {
+ // Get Artists and set the table model
+ MusicBrainzArtist[] artists = reader.getArtists();
+ for (MusicBrainzArtist artist : artists) {
+ addId(artist.getId());
+ }
+ setSearchStatus("All done!", "green");
+ searchTable.setModel(reader.getArtistsAsTableModel(artists));
+ }
+ case "Release" -> {
+ // Get Releases and set the table model
+ MusicBrainzRelease[] releases = reader.getReleases();
+ for (MusicBrainzRelease release : releases) {
+ addId(release.getId());
+ }
+ setSearchStatus("All done!", "green");
+ searchTable.setModel(reader.getReleasesAsTableModel(releases));
+ }
+ default -> JOptionPane.showMessageDialog(panel, "Please select a search type.");
+ }
+ });
+
resizeColumnWidths(searchTable);
});
@@ -176,33 +206,30 @@ private MusicBrainzJSONReader sendRequest(String queryType, String query) {
}
/**
- * Gets a default table model for CDStubs.
- * @return A DefaultTableModel with the correct columns.
- */
- private DefaultTableModel getCDStubModel() {
- String[] columnNames = {"Disc Name", "Artist", "Track Count", ""};
- String[][] data = {{"", "", "", ""}};
- return new javax.swing.table.DefaultTableModel(data, columnNames);
- }
-
- /**
- * Gets a default table model for Artists.
- * @return A DefaultTableModel with the correct columns.
+ * Helper method to get a table model
+ * @param model The model to get.
*/
- private DefaultTableModel getArtistModel() {
- String[] columnNames = {"Name", "Date Organised", "Birthdate", "Sort Name", "Gender", "Type", "Disambiguation", "Life Span", "Country", ""};
- String[][] data = {{"", "", "", "", "", "", "", ""}};
- return new javax.swing.table.DefaultTableModel(data, columnNames);
- }
-
- /**
- * Gets a default table model for Releases.
- * @return A DefaultTableModel with the correct columns.
- */
- private DefaultTableModel getReleaseModel() {
- String[] columnNames = {"Release Name", "Artist", "Track Count", "Date", ""};
- String[][] data = {{"", "", "", ""}};
- return new javax.swing.table.DefaultTableModel(data, columnNames);
+ private DefaultTableModel getTableModel(String model) {
+ switch (model) {
+ case "CDStub" -> {
+ String[] columnNames = {"Disc Name", "Artist", "Track Count"};
+ String[][] data = {{"", "", ""}};
+ return new DefaultTableModel(data, columnNames);
+ }
+ case "Artist" -> {
+ String[] columnNames = {"Artist Name", "Date Organised", "Birthdate", "Sort Name", "Gender", "Type", "Disambiguation", "Life Span", "Country"};
+ String[][] data = {{"", "", "", "", "", "", ""}};
+ return new DefaultTableModel(data, columnNames);
+ }
+ case "Release" -> {
+ String[] columnNames = {"Release Name", "Artist", "Track Count", "Date"};
+ String[][] data = {{"", "", ""}};
+ return new DefaultTableModel(data, columnNames);
+ }
+ default -> {
+ return new DefaultTableModel(new String [][] {{}}, new String[] {});
+ }
+ }
}
/**
@@ -326,7 +353,93 @@ private void resizeColumnWidths(JTable table) {
}
}
+ /**
+ * Sets the search status label.
+ * @param status The status to set.
+ * @param color The color to set.
+ */
public void setSearchStatus(String status, String color) {
searchStatusLabel.setText("Status: " + status + "");
}
+
+ /**
+ * Adds an ID to the list of IDs.
+ * @param id The ID to add.
+ */
+ public static void addId(String id) {
+ idList.add(id);
+ }
+
+ /**
+ * Clears the list of IDs.
+ */
+ public static void clearIdList() {
+ idList.clear();
+ }
+
+ /**
+ * Helper method to search specific data (Artists, Releases, etc.) in the search table.
+ * @param row The row where the object is located.
+ * @param col The column where the object is located.
+ */
+ private void clickSearch(int row, int col, JTable table) {
+ String typeOfTable = table.getColumnName(0);
+ System.out.println("Clicked at: " + row + ", " + col);
+ switch (typeOfTable) {
+ case "Disc Name" -> {
+ if (col == 0 && row >= 0) {
+ setSearchStatus("Fetching Tracks...", "blue");
+ System.out.println("This kinda works");
+ String response = getDiscTrackListResponseString(row);
+ MusicBrainzJSONReader reader = new MusicBrainzJSONReader(response);
+ DefaultTableModel model = reader.getTracksAsTableModel(reader.getTracks());
+ JTable trackTable = new JTable(model);
+ resizeColumnWidths(trackTable);
+ JScrollPane trackScrollPane = new JScrollPane(trackTable);
+ setSearchStatus("All Done!", "green");
+ JOptionPane.showMessageDialog(null, trackScrollPane, "Tracks", JOptionPane.PLAIN_MESSAGE);
+ }
+ }
+ case "Release Name" -> {
+ if (col == 0 && row >= 0) {
+ setSearchStatus("Fetching Tracks...", "blue");
+ System.out.println("This also kinda works");
+ String response = getReleaseTrackListResponseString(row);
+ MusicBrainzJSONReader reader = new MusicBrainzJSONReader(response);
+ DefaultTableModel model = reader.getTracksAsTableModel(reader.getReleaseTracks());
+ JTable trackTable = new JTable(model);
+ resizeColumnWidths(trackTable);
+ JScrollPane trackScrollPane = new JScrollPane(trackTable);
+ setSearchStatus("All Done!", "green");
+ JOptionPane.showMessageDialog(null, trackScrollPane, "Tracks", JOptionPane.PLAIN_MESSAGE);
+ }
+ }
+ }
+ }
+
+ private String getDiscTrackListResponseString(int row) {
+ MusicBrainzRequest request = new MusicBrainzRequest("tracks", idList.get(row));
+ WebRequest webRequest = new WebRequest(request.buildTrackListURL(), userAgent);
+ String response;
+ try {
+ response = webRequest.sendRequest();
+ } catch (IOException | URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ return response;
+ }
+
+ private String getReleaseTrackListResponseString(int row) {
+ MusicBrainzRequest request = new MusicBrainzRequest("release", idList.get(row));
+ WebRequest webRequest = new WebRequest(request.buildTrackListURL(), userAgent);
+ String response;
+ try {
+ response = webRequest.sendRequest();
+ } catch (IOException | URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ return response;
+ }
+
+
}
\ No newline at end of file
diff --git a/src/main/java/com/CDPrintable/WebRequest.java b/src/main/java/com/CDPrintable/WebRequest.java
index 9de6e0f..a9b3663 100644
--- a/src/main/java/com/CDPrintable/WebRequest.java
+++ b/src/main/java/com/CDPrintable/WebRequest.java
@@ -43,6 +43,16 @@ public WebRequest(String url, String userAgent) {
this.userAgent = userAgent;
}
+ /**
+ * Constructor for WebRequest. Makes a web request to the MusicBrainz API according to the given URL.
+ * @param url The URL to use.
+ * @param userAgent The user agent to use.
+ */
+ public WebRequest(String url, UserAgent userAgent) {
+ this.url = url;
+ this.userAgent = userAgent.toString();
+ }
+
/**
* Sends the request to the MusicBrainz API and returns the response.
* @return The response from the MusicBrainz API.
diff --git a/src/main/resources/version.properties b/src/main/resources/version.properties
index da0fc6f..b35e558 100644
--- a/src/main/resources/version.properties
+++ b/src/main/resources/version.properties
@@ -1,4 +1,4 @@
# Application version.
# MAJOR MINOR PATCH
-version=1.7.5
\ No newline at end of file
+version=1.8.5
\ No newline at end of file
diff --git a/src/test/java/MusicBrainzObjectTests.java b/src/test/java/MusicBrainzObjectTests.java
index 89c3f4a..916fa90 100644
--- a/src/test/java/MusicBrainzObjectTests.java
+++ b/src/test/java/MusicBrainzObjectTests.java
@@ -242,19 +242,17 @@ void genericGetReleasesAsTableModelTest() {
assertNotNull(tableModel);
assertEquals(2, tableModel.getRowCount());
- assertEquals(5, tableModel.getColumnCount());
+ assertEquals(4, tableModel.getColumnCount());
assertEquals("Nights Like This", tableModel.getValueAt(0, 0));
assertEquals("Witt Lowry", tableModel.getValueAt(0, 1));
assertEquals("1", tableModel.getValueAt(0, 2));
assertEquals("2022-10-28", tableModel.getValueAt(0, 3));
- assertEquals("", tableModel.getValueAt(0, 4));
assertEquals("Nights Like This", tableModel.getValueAt(1, 0));
assertEquals("Kaylee Bell", tableModel.getValueAt(1, 1));
assertEquals("11", tableModel.getValueAt(1, 2));
assertEquals("", tableModel.getValueAt(1, 3));
- assertEquals("", tableModel.getValueAt(1, 4));
}
/**
@@ -270,17 +268,15 @@ void genericGetCDStubsAsTableModelTest() {
assertNotNull(tableModel);
assertEquals(2, tableModel.getRowCount());
- assertEquals(4, tableModel.getColumnCount());
+ assertEquals(3, tableModel.getColumnCount());
assertEquals("Songs From The Big Chair", tableModel.getValueAt(0, 0));
assertEquals("Tears For Fears", tableModel.getValueAt(0, 1));
assertEquals("8", tableModel.getValueAt(0, 2));
- assertEquals("", tableModel.getValueAt(0, 3));
assertEquals("+", tableModel.getValueAt(1, 0));
assertEquals("Ed Sheeran", tableModel.getValueAt(1, 1));
assertEquals("13", tableModel.getValueAt(1, 2));
- assertEquals("", tableModel.getValueAt(1, 3));
}
/**
@@ -296,7 +292,7 @@ void genericGetArtistsAsTableModelTest() {
assertNotNull(tableModel);
assertEquals(2, tableModel.getRowCount());
- assertEquals(10, tableModel.getColumnCount());
+ assertEquals(9, tableModel.getColumnCount());
assertEquals("Tears for Fears", tableModel.getValueAt(0, 0));
assertEquals("1981", tableModel.getValueAt(0, 1));
@@ -307,7 +303,6 @@ void genericGetArtistsAsTableModelTest() {
assertEquals("new wave", tableModel.getValueAt(0, 6));
assertEquals("", tableModel.getValueAt(0, 7));
assertEquals("United Kingdom", tableModel.getValueAt(0, 8));
- assertEquals("", tableModel.getValueAt(0, 9));
assertEquals("The Kid LAROI", tableModel.getValueAt(1, 0));
assertEquals("", tableModel.getValueAt(1, 1));
@@ -318,7 +313,6 @@ void genericGetArtistsAsTableModelTest() {
assertEquals("hip hop", tableModel.getValueAt(1, 6));
assertEquals("", tableModel.getValueAt(1, 7));
assertEquals("Australia", tableModel.getValueAt(1, 8));
- assertEquals("", tableModel.getValueAt(1, 9));
}
/**
diff --git a/src/test/resources/DiscIDExample.json b/src/test/resources/DiscIDExample.json
new file mode 100644
index 0000000..80a3035
--- /dev/null
+++ b/src/test/resources/DiscIDExample.json
@@ -0,0 +1,50 @@
+{
+ "disambiguation": "",
+ "tracks": [
+ {
+ "length": 393293,
+ "title": "Shout",
+ "artist": null
+ },
+ {
+ "title": "The Working Hour",
+ "artist": null,
+ "length": 391573
+ },
+ {
+ "length": 251466,
+ "artist": null,
+ "title": "Everybody Wants To Rule The World"
+ },
+ {
+ "length": 309800,
+ "artist": null,
+ "title": "Mothers Talk"
+ },
+ {
+ "title": "I Believe",
+ "artist": null,
+ "length": 295066
+ },
+ {
+ "artist": null,
+ "title": "Broken",
+ "length": 158426
+ },
+ {
+ "length": 301800,
+ "title": "Head Over Heels / Broken (Live)",
+ "artist": null
+ },
+ {
+ "title": "Listen",
+ "artist": null,
+ "length": 411000
+ }
+ ],
+ "artist": "Tears For Fears",
+ "barcode": "042282430021",
+ "id": "hU2FJcnlVtratcrOn9rAhPzzCMo-",
+ "title": "Songs From The Big Chair",
+ "track-count": 8
+}
\ No newline at end of file
diff --git a/src/test/resources/ReleaseTrackListExample.json b/src/test/resources/ReleaseTrackListExample.json
new file mode 100644
index 0000000..496dd7f
--- /dev/null
+++ b/src/test/resources/ReleaseTrackListExample.json
@@ -0,0 +1,353 @@
+{
+ "status-id": "4e304316-386d-3409-af2e-78857eec5cfe",
+ "id": "adb7389e-d1ee-4c66-abec-28e2670619a3",
+ "text-representation": {
+ "script": null,
+ "language": "eng"
+ },
+ "title": "THE FIRST TIME",
+ "packaging": "Box",
+ "date": "2023-12-05",
+ "quality": "normal",
+ "asin": null,
+ "barcode": "196588049521",
+ "cover-art-archive": {
+ "count": 3,
+ "artwork": true,
+ "darkened": false,
+ "back": true,
+ "front": true
+ },
+ "disambiguation": "Box Set CD",
+ "packaging-id": "c1668fc7-8944-4a00-bc3e-46e8d861d211",
+ "status": "Official",
+ "country": "US",
+ "release-events": [
+ {
+ "area": {
+ "name": "United States",
+ "iso-3166-1-codes": [
+ "US"
+ ],
+ "disambiguation": "",
+ "type-id": null,
+ "id": "489ce91b-6658-3307-9877-795b68554c98",
+ "type": null,
+ "sort-name": "United States"
+ },
+ "date": "2023-12-05"
+ }
+ ],
+ "media": [
+ {
+ "format": "CD",
+ "track-offset": 0,
+ "format-id": "9712d52a-4509-3d4b-a1a2-67c88c643e31",
+ "title": "",
+ "track-count": 20,
+ "tracks": [
+ {
+ "title": "SORRY",
+ "position": 1,
+ "id": "8809748b-092e-4bd2-9a1c-ca10ee1e2768",
+ "length": 192000,
+ "number": "1",
+ "recording": {
+ "disambiguation": "",
+ "first-release-date": "2023-11-10",
+ "video": false,
+ "title": "SORRY",
+ "id": "4d1cc7fc-3439-4a54-b703-2075c7da205b",
+ "length": 192000
+ }
+ },
+ {
+ "recording": {
+ "video": false,
+ "title": "BLEED",
+ "id": "17e8a0a7-9643-41ad-8097-9581c9b1a5c9",
+ "length": 169000,
+ "disambiguation": "",
+ "first-release-date": "2023-11-10"
+ },
+ "number": "2",
+ "position": 2,
+ "id": "4acb232c-780d-4a1c-aeaf-11fbe9ad3525",
+ "length": 170000,
+ "title": "BLEED"
+ },
+ {
+ "title": "I THOUGHT THAT I NEEDED YOU",
+ "position": 3,
+ "id": "4cfbd92f-01f3-4d07-8331-f83c2dc9fa9f",
+ "length": 171000,
+ "number": "3",
+ "recording": {
+ "title": "I THOUGHT THAT I NEEDED YOU",
+ "video": false,
+ "id": "bdb76ec0-64ef-4767-a8e2-c1a971fd6e69",
+ "length": 171000,
+ "disambiguation": "",
+ "first-release-date": "2023-11-10"
+ }
+ },
+ {
+ "title": "WHERE DO YOU SLEEP?",
+ "number": "4",
+ "recording": {
+ "title": "WHERE DO YOU SLEEP?",
+ "video": false,
+ "id": "ab91d2ca-ea61-4622-a3ff-3d8d2b04bb14",
+ "length": 192000,
+ "disambiguation": "",
+ "first-release-date": "2023-11-10"
+ },
+ "position": 4,
+ "length": 192000,
+ "id": "60be45d8-f1d7-43fa-bdcc-acb1a8eed96a"
+ },
+ {
+ "number": "5",
+ "recording": {
+ "video": false,
+ "title": "TOO MUCH",
+ "id": "1f1e249c-deb2-4672-aaeb-b18d4c24cc57",
+ "length": 203000,
+ "disambiguation": "",
+ "first-release-date": "2023-10-19"
+ },
+ "position": 5,
+ "id": "0d6e6cf0-5e61-45d9-9d3d-861ed7a19b7b",
+ "length": 204000,
+ "title": "TOO MUCH"
+ },
+ {
+ "title": "TEAR ME APART",
+ "length": 115000,
+ "position": 6,
+ "id": "21143a91-79ea-4f3e-9dc0-d554944cdd23",
+ "recording": {
+ "disambiguation": "",
+ "first-release-date": "2023-11-10",
+ "video": false,
+ "title": "TEAR ME APART",
+ "id": "5a99b1a2-ba12-4915-821e-53b7a70b0f63",
+ "length": 114000
+ },
+ "number": "6"
+ },
+ {
+ "title": "STRANGERS (Interlude)",
+ "position": 7,
+ "id": "86a8500c-d24f-43c5-8460-e84f92ae6dbe",
+ "length": 26000,
+ "number": "7",
+ "recording": {
+ "disambiguation": "",
+ "first-release-date": "2023-11-10",
+ "video": false,
+ "title": "STRANGERS (Interlude)",
+ "id": "60aeaaf3-6880-4a46-8e8e-6354cd36e524",
+ "length": 25000
+ }
+ },
+ {
+ "length": 87000,
+ "position": 8,
+ "id": "17663fde-299e-4687-a728-776ec10053b5",
+ "recording": {
+ "first-release-date": "2023-11-10",
+ "disambiguation": "",
+ "id": "1942ae28-ee62-47ba-b1bd-a98264cbaf9b",
+ "length": 86026,
+ "video": false,
+ "title": "NIGHTS LIKE THIS"
+ },
+ "number": "8",
+ "title": "NIGHTS LIKE THIS"
+ },
+ {
+ "position": 9,
+ "id": "4adc5e48-c6f3-4bec-ada1-26c4bae0938e",
+ "length": 200000,
+ "number": "9",
+ "recording": {
+ "disambiguation": "",
+ "first-release-date": "2023-11-08",
+ "video": false,
+ "title": "WHAT'S THE MOVE?",
+ "id": "de76245a-f9df-4b08-91bb-0a713e7e3ee8",
+ "length": 199000
+ },
+ "title": "WHAT'S THE MOVE?"
+ },
+ {
+ "id": "f25c9ab5-396a-499c-a3c1-7a2b0b05b1b6",
+ "position": 10,
+ "length": 44000,
+ "number": "10",
+ "recording": {
+ "disambiguation": "",
+ "first-release-date": "2023-11-10",
+ "title": "STRANGERS PT 2 (Interlude)",
+ "video": false,
+ "length": 43000,
+ "id": "91d92c2e-21fe-4c24-b314-a325ffc83d13"
+ },
+ "title": "STRANGERS PT 2 (Interlude)"
+ },
+ {
+ "title": "CALL ME INSTEAD",
+ "recording": {
+ "video": false,
+ "title": "CALL ME INSTEAD",
+ "id": "927251d4-29ee-4c7e-893f-1a8c0b55b3c9",
+ "length": 197000,
+ "disambiguation": "",
+ "first-release-date": "2023-11-10"
+ },
+ "number": "11",
+ "position": 11,
+ "length": 198000,
+ "id": "6ed3dc24-e0cc-4752-84f5-e848fe357f43"
+ },
+ {
+ "title": "DESERVE YOU",
+ "length": 158000,
+ "position": 12,
+ "id": "8d6c56b2-7da4-4f29-9d1b-66931b58ec2f",
+ "number": "12",
+ "recording": {
+ "id": "b46ede98-fb31-44fd-a2f9-f06cb8ab244d",
+ "length": 157000,
+ "title": "DESERVE YOU",
+ "video": false,
+ "first-release-date": "2023-11-10",
+ "disambiguation": ""
+ }
+ },
+ {
+ "position": 13,
+ "length": 157000,
+ "id": "7e683017-4777-4b78-a156-d3449b5a36c0",
+ "number": "13",
+ "recording": {
+ "length": 157000,
+ "id": "57775c9c-fd13-4a08-a293-cff391e3f1ce",
+ "video": false,
+ "title": "WHAT WENT WRONG???",
+ "first-release-date": "2023-11-10",
+ "disambiguation": ""
+ },
+ "title": "WHAT WENT WRONG???"
+ },
+ {
+ "title": "THE LINE",
+ "id": "eb820330-e498-4db0-a70e-ca2c607c4a7f",
+ "position": 14,
+ "length": 152000,
+ "number": "14",
+ "recording": {
+ "id": "7bf488d0-a544-4a98-a559-9edd6982cf77",
+ "length": 152000,
+ "title": "THE LINE",
+ "video": false,
+ "first-release-date": "2023-11-10",
+ "disambiguation": ""
+ }
+ },
+ {
+ "recording": {
+ "first-release-date": "2023-10-27",
+ "disambiguation": "",
+ "id": "2bc0c09b-4778-4b30-9a4c-c1283d0bf962",
+ "length": 162191,
+ "video": false,
+ "title": "WHAT JUST HAPPENED"
+ },
+ "number": "15",
+ "position": 15,
+ "id": "07a27871-0e51-4b71-ad13-45a75b15ad01",
+ "length": 163000,
+ "title": "WHAT JUST HAPPENED"
+ },
+ {
+ "title": "YOU",
+ "recording": {
+ "length": 136000,
+ "id": "781f35c1-bb1d-42da-81ee-97249dfabef2",
+ "video": false,
+ "title": "YOU",
+ "first-release-date": "2023-11-10",
+ "disambiguation": ""
+ },
+ "number": "16",
+ "position": 16,
+ "length": 137000,
+ "id": "40999131-46b8-4730-9b69-28962043cbb8"
+ },
+ {
+ "title": "LOVE AGAIN",
+ "position": 17,
+ "length": 146000,
+ "id": "e9986e68-484c-4e44-b7be-64808017a1f2",
+ "recording": {
+ "first-release-date": "2023-12-05",
+ "disambiguation": "",
+ "length": 146000,
+ "id": "e27a5230-d366-446e-9896-6d35ee645301",
+ "title": "LOVE AGAIN",
+ "video": false
+ },
+ "number": "17"
+ },
+ {
+ "title": "WHERE DOES YOUR SPIRIT GO?",
+ "id": "518c87a7-e732-4904-abca-02bdea055b25",
+ "position": 18,
+ "length": 206000,
+ "number": "18",
+ "recording": {
+ "first-release-date": "2023-11-10",
+ "disambiguation": "",
+ "id": "d9997735-2a35-4dde-9c2c-39f7f39b3a8d",
+ "length": 205000,
+ "title": "WHERE DOES YOUR SPIRIT GO?",
+ "video": false
+ }
+ },
+ {
+ "title": "YOU NEVER FORGET YOUR FIRST TIME...",
+ "id": "979105be-c395-4588-a31f-0b8589f18f5d",
+ "position": 19,
+ "length": 125000,
+ "number": "19",
+ "recording": {
+ "disambiguation": "",
+ "first-release-date": "2023-11-10",
+ "video": false,
+ "title": "YOU NEVER FORGET YOUR FIRST TIME...",
+ "id": "842d2b28-ac2a-4e78-a08b-025d290f29b8",
+ "length": 124000
+ }
+ },
+ {
+ "title": "KIDS ARE GROWING UP",
+ "recording": {
+ "video": false,
+ "title": "KIDS ARE GROWING UP",
+ "id": "32a931b4-9b51-49a9-b858-88267c1ccde5",
+ "length": 260000,
+ "disambiguation": "",
+ "first-release-date": "2023-11-10"
+ },
+ "number": "20",
+ "position": 20,
+ "id": "44667368-5ef7-47c4-9b97-9a90466cb6fc",
+ "length": 261000
+ }
+ ],
+ "position": 1
+ }
+ ]
+}
\ No newline at end of file