Add marker for unknown 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         // OBJECT METHODS
241         //
242
243         @Override
244         public int hashCode() {
245                 return formatMetadata.hashCode() ^ contentMetadata.hashCode();
246         }
247
248         @Override
249         public boolean equals(Object object) {
250                 if (!(object instanceof Metadata)) {
251                         return false;
252                 }
253                 Metadata metadata = (Metadata) object;
254                 return formatMetadata.equals(metadata.formatMetadata) && contentMetadata.equals(metadata.contentMetadata);
255         }
256
257         @Override
258         public String toString() {
259                 return String.format("%s%s%s", formatMetadata, contentMetadata.toString().length() > 0 ? ": " : "", contentMetadata);
260         }
261
262 }