cdfc4d2c826d7c30cc604599f9422472c73de500
[sonitus.git] / src / main / java / net / pterodactylus / sonitus / data / ContentMetadata.java
1 /*
2  * Sonitus - ContentMetadata.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 java.util.Arrays;
21
22 import com.google.common.base.Joiner;
23 import com.google.common.base.Optional;
24 import com.google.common.base.Preconditions;
25
26 /**
27  * The part of the {@link Metadata} that contains information about the content
28  * of a {@link Source}, such as the name of the track, the artist, or other
29  * information.
30  * <p/>
31  * Content metadata also contains a “title” which is an amalgamation of all
32  * information in the content metadata. If not given, it will be automatically
33  * constructed from all other information. If can also be specified manually to
34  * override the default.
35  *
36  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
37  */
38 public class ContentMetadata {
39
40         /** The artist. */
41         private final Optional<String> artist;
42
43         /** The name. */
44         private final Optional<String> name;
45
46         /** The all-in-one title. */
47         private final String title;
48
49         /** Creates empty content metadata. */
50         public ContentMetadata() {
51                 this("");
52         }
53
54         /**
55          * Creates content metadata containing the given title.
56          *
57          * @param title
58          *              The title of the metadata
59          * @throws NullPointerException
60          *              if {@code title} is {@code null}
61          */
62         public ContentMetadata(String title) throws NullPointerException {
63                 this(null, null, title);
64         }
65
66         /**
67          * Creates content metadata.
68          *
69          * @param artist
70          *              The artist of the track
71          * @param name
72          *              The name of the track
73          */
74         public ContentMetadata(String artist, String name) {
75                 this(artist, name, joinStrings(artist, name));
76         }
77
78         /**
79          * Creates content metadata.
80          *
81          * @param artist
82          *              The artist of the track (may be null)
83          * @param name
84          *              The name of the track (may be null)
85          * @param title
86          *              The title of the track
87          * @throws NullPointerException
88          *              if {@code title} is {@code null}
89          */
90         private ContentMetadata(String artist, String name, String title) throws NullPointerException {
91                 this.artist = Optional.fromNullable(artist);
92                 this.name = Optional.fromNullable(name);
93                 this.title = Preconditions.checkNotNull(title, "title must not be null");
94         }
95
96         //
97         // ACCESSORS
98         //
99
100         /**
101          * Returns the artist of the track, if it has been set.
102          *
103          * @return The artist of the track
104          */
105         public Optional<String> artist() {
106                 return artist;
107         }
108
109         /**
110          * Returns the name of the track, if it has been set.
111          *
112          * @return The name of the track
113          */
114         public Optional<String> name() {
115                 return name;
116         }
117
118         /**
119          * Returns the title of the track.
120          *
121          * @return The title of the track
122          */
123         public String title() {
124                 return title;
125         }
126
127         //
128         // ACTIONS
129         //
130
131         /**
132          * Creates new content metadata that is a copy of this content metadata but
133          * with the artist changed. The title will be reconstructed from the new artist
134          * and the existing name.
135          *
136          * @param artist
137          *              The new artist
138          * @return The new content metadata
139          */
140         public ContentMetadata artist(String artist) {
141                 return new ContentMetadata(artist, name().orNull(), joinStrings(artist, name().orNull()));
142         }
143
144         /**
145          * Creates new content metadata that is a copy of this content metadata but
146          * with the name changed. The title will be reconstructed from the existing
147          * artist and the new name.
148          *
149          * @param name
150          *              The new name
151          * @return The new content metadata
152          */
153         public ContentMetadata name(String name) {
154                 return new ContentMetadata(artist().orNull(), name, joinStrings(artist().orNull(), name));
155         }
156
157         /**
158          * Creates new content metadata that is a copy of this content metadata but
159          * with the title changed.
160          *
161          * @param title
162          *              The new title
163          * @return The new content metadata
164          */
165         public ContentMetadata title(String title) {
166                 return new ContentMetadata(artist().orNull(), name().orNull(), title);
167         }
168
169         //
170         // OBJECT METHODS
171         //
172
173         @Override
174         public int hashCode() {
175                 return artist().hashCode() ^ name().hashCode() ^ title().hashCode();
176         }
177
178         @Override
179         public boolean equals(Object object) {
180                 if (!(object instanceof ContentMetadata)) {
181                         return false;
182                 }
183                 ContentMetadata contentMetadata = (ContentMetadata) object;
184                 return artist().equals(contentMetadata.artist()) && name().equals(contentMetadata.name()) && title().equals(contentMetadata.title());
185         }
186
187         @Override
188         public String toString() {
189                 return title;
190         }
191
192         //
193         // STATIC METHODS
194         //
195
196         /**
197          * Joins the given strings, concatenating them with “ - ” and ignoring {@code
198          * null} values.
199          *
200          * @param strings
201          *              The strings to join
202          * @return The joined strings
203          */
204         private static String joinStrings(String... strings) {
205                 return Joiner.on(" - ").skipNulls().join(Arrays.asList(strings));
206         }
207
208 }