Add equals() method that ignores the comment of the content metadata.
[sonitus.git] / src / main / java / net / pterodactylus / sonitus / data / Metadata.java
1 /*
2  * Sonitus - Metainfo.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sonitus.data;
19
20 import com.google.common.base.Optional;
21
22 /**
23  * Metadata contains information about a source, e.g. the number of channels,
24  * the frequency, the encoding, the name of the content, the artist performing
25  * it, dates, comments, URLs, etc.
26  * <p/>
27  * Metadata, once created, is immutable.
28  *
29  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
30  */
31 public class Metadata {
32
33         /** Marker for unknown metadata. */
34         public static final Metadata UNKNOWN = new Metadata();
35
36         /** The format metadata. */
37         private final FormatMetadata formatMetadata;
38
39         /** The content metadata. */
40         private final ContentMetadata contentMetadata;
41
42         /** Creates empty metadata. */
43         public Metadata() {
44                 this(new FormatMetadata(), new ContentMetadata());
45         }
46
47         /**
48          * Creates metadata from the given format and content metadata.
49          *
50          * @param formatMetadata
51          *              The format metadata
52          * @param contentMetadata
53          *              The content metadata
54          */
55         public Metadata(FormatMetadata formatMetadata, ContentMetadata contentMetadata) {
56                 this.formatMetadata = formatMetadata;
57                 this.contentMetadata = contentMetadata;
58         }
59
60         //
61         // ACCESSORS
62         //
63
64         /**
65          * Returns the embedded format metadata.
66          *
67          * @return The format metadata
68          */
69         public FormatMetadata format() {
70                 return formatMetadata;
71         }
72
73         /**
74          * Returns the embedded content metadata.
75          *
76          * @return The content metadata
77          */
78         public ContentMetadata content() {
79                 return contentMetadata;
80         }
81
82         /**
83          * Returns the number of channels of this metadata.
84          *
85          * @return The number of channels of this metadata
86          */
87         public int channels() {
88                 return formatMetadata.channels();
89         }
90
91         /**
92          * Returns a metadata with the same parameters as this metadata and the given
93          * number of channels.
94          *
95          * @param channels
96          *              The new number of channels
97          * @return A new metadata with the given number of channels
98          */
99         public Metadata channels(int channels) {
100                 return new Metadata(formatMetadata.channels(channels), contentMetadata);
101         }
102
103         /**
104          * Returns the sampling frequency of this metadata.
105          *
106          * @return The sampling frequency of this metadata
107          */
108         public int frequency() {
109                 return formatMetadata.frequency();
110         }
111
112         /**
113          * Returns a new metadata with the same parameters as this metadata and the
114          * given frequency.
115          *
116          * @param frequency
117          *              The new frequency
118          * @return A new metadata with the given frequency
119          */
120         public Metadata frequency(int frequency) {
121                 return new Metadata(formatMetadata.frequency(frequency), contentMetadata);
122         }
123
124         /**
125          * Returns the encoding of this metadata
126          *
127          * @return The encoding of this metadata
128          */
129         public String encoding() {
130                 return formatMetadata.encoding();
131         }
132
133         /**
134          * Returns a new metadata with the same parameters as this metadata and the
135          * given encoding.
136          *
137          * @param encoding
138          *              The new encoding
139          * @return A new metadata with the given encoding
140          */
141         public Metadata encoding(String encoding) {
142                 return new Metadata(formatMetadata.encoding(encoding), contentMetadata);
143         }
144
145         /**
146          * Returns the artist, if any.
147          *
148          * @return The artist, or {@link Optional#absent()}
149          */
150         public Optional<String> artist() {
151                 return contentMetadata.artist();
152         }
153
154         /**
155          * Returns new metadata with the same attributes as this metadata, except for
156          * the artist.
157          *
158          * @param artist
159          *              The new artist
160          * @return New metadata with a changed artist
161          */
162         public Metadata artist(String artist) {
163                 return new Metadata(formatMetadata, contentMetadata.artist(artist));
164         }
165
166         /**
167          * Returns the name of the content, if any.
168          *
169          * @return The name, or {@link Optional#absent()}
170          */
171         public Optional<String> name() {
172                 return contentMetadata.name();
173         }
174
175         /**
176          * Returns new metadata with the same attributes as this metadata, except for
177          * the name.
178          *
179          * @param name
180          *              The new name
181          * @return New metadata with a changed name
182          */
183         public Metadata name(String name) {
184                 return new Metadata(formatMetadata, contentMetadata.name(name));
185         }
186
187         /**
188          * Returns the title of the content.
189          *
190          * @return The title of the content
191          */
192         public String title() {
193                 return contentMetadata.title();
194         }
195
196         /**
197          * Returns new metadata with the same attributes as this metadata but with the
198          * title changed to the given title.
199          *
200          * @param title
201          *              The new title
202          * @return The new metadata
203          */
204         public Metadata title(String title) {
205                 return new Metadata(formatMetadata, contentMetadata.title(title));
206         }
207
208         /**
209          * Returns the comment of the content, if any.
210          *
211          * @return The comment of the content
212          */
213         public Optional<String> comment() {
214                 return contentMetadata.comment();
215         }
216
217         /**
218          * Returns new metadata with the same attributes as this metadata but with the
219          * comment changed to the given comment.
220          *
221          * @param comment
222          *              The new comment
223          * @return The new metadata
224          */
225         public Metadata comment(String comment) {
226                 return new Metadata(formatMetadata, contentMetadata.comment(comment));
227         }
228
229         /**
230          * Returns the title with the comment appended in parantheses, if a comment has
231          * been set.
232          *
233          * @return The title with the comment appended
234          */
235         public String fullTitle() {
236                 return String.format("%s%s", title(), comment().isPresent() ? String.format(" (%s)", comment().get()) : "");
237         }
238
239         /**
240          * Returns whether this metadata object equals the given object if the comments
241          * of this and the given object are ignored.
242          *
243          * @param object
244          *              The object to compare to this one
245          * @return {@code true} if the given object and this object are equal if the
246          *         comments are ignored, {@code false} otherwise
247          */
248         public boolean equalsIgnoreComment(Object object) {
249                 if (!(object instanceof Metadata)) {
250                         return false;
251                 }
252                 Metadata metadata = (Metadata) object;
253                 return formatMetadata.equals(metadata.formatMetadata) && contentMetadata.equalsIgnoreComment(metadata.contentMetadata);
254         }
255
256         //
257         // OBJECT METHODS
258         //
259
260         @Override
261         public int hashCode() {
262                 return formatMetadata.hashCode() ^ contentMetadata.hashCode();
263         }
264
265         @Override
266         public boolean equals(Object object) {
267                 if (!(object instanceof Metadata)) {
268                         return false;
269                 }
270                 Metadata metadata = (Metadata) object;
271                 return formatMetadata.equals(metadata.formatMetadata) && contentMetadata.equals(metadata.contentMetadata);
272         }
273
274         @Override
275         public String toString() {
276                 return String.format("%s%s%s", formatMetadata, contentMetadata.toString().length() > 0 ? ": " : "", contentMetadata);
277         }
278
279 }