Merge branch 'release/0.9-rc1'
[Sone.git] / src / main / java / net / pterodactylus / sone / core / ConfigurationSoneParser.java
1 package net.pterodactylus.sone.core;
2
3 import static java.util.Collections.unmodifiableMap;
4
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import javax.annotation.Nullable;
13
14 import net.pterodactylus.sone.data.Album;
15 import net.pterodactylus.sone.data.Image;
16 import net.pterodactylus.sone.data.Post;
17 import net.pterodactylus.sone.data.PostReply;
18 import net.pterodactylus.sone.data.Profile;
19 import net.pterodactylus.sone.data.Sone;
20 import net.pterodactylus.sone.database.AlbumBuilderFactory;
21 import net.pterodactylus.sone.database.ImageBuilderFactory;
22 import net.pterodactylus.sone.database.PostBuilder;
23 import net.pterodactylus.sone.database.PostBuilderFactory;
24 import net.pterodactylus.sone.database.PostReplyBuilder;
25 import net.pterodactylus.sone.database.PostReplyBuilderFactory;
26 import net.pterodactylus.util.config.Configuration;
27
28 /**
29  * Parses a {@link Sone}’s data from a {@link Configuration}.
30  *
31  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
32  */
33 public class ConfigurationSoneParser {
34
35         private final Configuration configuration;
36         private final Sone sone;
37         private final String sonePrefix;
38         private final Map<String, Album> albums = new HashMap<String, Album>();
39         private final List<Album> topLevelAlbums = new ArrayList<Album>();
40         private final Map<String, Image> images = new HashMap<String, Image>();
41
42         public ConfigurationSoneParser(Configuration configuration, Sone sone) {
43                 this.configuration = configuration;
44                 this.sone = sone;
45                 sonePrefix = "Sone/" + sone.getId();
46         }
47
48         public Profile parseProfile() {
49                 Profile profile = new Profile(sone);
50                 profile.setFirstName(getString("/Profile/FirstName", null));
51                 profile.setMiddleName(getString("/Profile/MiddleName", null));
52                 profile.setLastName(getString("/Profile/LastName", null));
53                 profile.setBirthDay(getInt("/Profile/BirthDay", null));
54                 profile.setBirthMonth(getInt("/Profile/BirthMonth", null));
55                 profile.setBirthYear(getInt("/Profile/BirthYear", null));
56
57                 /* load profile fields. */
58                 int fieldCount = 0;
59                 while (true) {
60                         String fieldPrefix = "/Profile/Fields/" + fieldCount++;
61                         String fieldName = getString(fieldPrefix + "/Name", null);
62                         if (fieldName == null) {
63                                 break;
64                         }
65                         String fieldValue = getString(fieldPrefix + "/Value", "");
66                         profile.addField(fieldName).setValue(fieldValue);
67                 }
68
69                 return profile;
70         }
71
72         private String getString(String nodeName, @Nullable String defaultValue) {
73                 return configuration.getStringValue(sonePrefix + nodeName)
74                                 .getValue(defaultValue);
75         }
76
77         private Integer getInt(String nodeName, @Nullable Integer defaultValue) {
78                 return configuration.getIntValue(sonePrefix + nodeName)
79                                 .getValue(defaultValue);
80         }
81
82         private Long getLong(String nodeName, @Nullable Long defaultValue) {
83                 return configuration.getLongValue(sonePrefix + nodeName)
84                                 .getValue(defaultValue);
85         }
86
87         public Set<Post> parsePosts(PostBuilderFactory postBuilderFactory)
88         throws InvalidPostFound {
89                 Set<Post> posts = new HashSet<Post>();
90                 while (true) {
91                         String postPrefix = "/Posts/" + posts.size();
92                         String postId = getString(postPrefix + "/ID", null);
93                         if (postId == null) {
94                                 break;
95                         }
96                         long postTime = getLong(postPrefix + "/Time", 0L);
97                         String postText = getString(postPrefix + "/Text", null);
98                         if (postAttributesAreInvalid(postTime, postText)) {
99                                 throw new InvalidPostFound();
100                         }
101                         PostBuilder postBuilder = postBuilderFactory.newPostBuilder()
102                                         .withId(postId)
103                                         .from(sone.getId())
104                                         .withTime(postTime)
105                                         .withText(postText);
106                         String postRecipientId =
107                                         getString(postPrefix + "/Recipient", null);
108                         if (postRecipientIsValid(postRecipientId)) {
109                                 postBuilder.to(postRecipientId);
110                         }
111                         posts.add(postBuilder.build());
112                 }
113                 return posts;
114         }
115
116         private boolean postAttributesAreInvalid(long postTime, String postText) {
117                 return (postTime == 0) || (postText == null);
118         }
119
120         private boolean postRecipientIsValid(String postRecipientId) {
121                 return (postRecipientId != null) && (postRecipientId.length() == 43);
122         }
123
124         public Set<PostReply> parsePostReplies(
125                         PostReplyBuilderFactory postReplyBuilderFactory) {
126                 Set<PostReply> replies = new HashSet<PostReply>();
127                 while (true) {
128                         String replyPrefix = "/Replies/" + replies.size();
129                         String replyId = getString(replyPrefix + "/ID", null);
130                         if (replyId == null) {
131                                 break;
132                         }
133                         String postId = getString(replyPrefix + "/Post/ID", null);
134                         long replyTime = getLong(replyPrefix + "/Time", 0L);
135                         String replyText = getString(replyPrefix + "/Text", null);
136                         if ((postId == null) || (replyTime == 0) || (replyText == null)) {
137                                 throw new InvalidPostReplyFound();
138                         }
139                         PostReplyBuilder postReplyBuilder = postReplyBuilderFactory
140                                         .newPostReplyBuilder()
141                                         .withId(replyId)
142                                         .from(sone.getId())
143                                         .to(postId)
144                                         .withTime(replyTime)
145                                         .withText(replyText);
146                         replies.add(postReplyBuilder.build());
147                 }
148                 return replies;
149         }
150
151         public Set<String> parseLikedPostIds() {
152                 Set<String> likedPostIds = new HashSet<String>();
153                 while (true) {
154                         String likedPostId =
155                                         getString("/Likes/Post/" + likedPostIds.size() + "/ID",
156                                                         null);
157                         if (likedPostId == null) {
158                                 break;
159                         }
160                         likedPostIds.add(likedPostId);
161                 }
162                 return likedPostIds;
163         }
164
165         public Set<String> parseLikedPostReplyIds() {
166                 Set<String> likedPostReplyIds = new HashSet<String>();
167                 while (true) {
168                         String likedReplyId = getString(
169                                         "/Likes/Reply/" + likedPostReplyIds.size() + "/ID", null);
170                         if (likedReplyId == null) {
171                                 break;
172                         }
173                         likedPostReplyIds.add(likedReplyId);
174                 }
175                 return likedPostReplyIds;
176         }
177
178         public Set<String> parseFriends() {
179                 Set<String> friends = new HashSet<String>();
180                 while (true) {
181                         String friendId =
182                                         getString("/Friends/" + friends.size() + "/ID", null);
183                         if (friendId == null) {
184                                 break;
185                         }
186                         friends.add(friendId);
187                 }
188                 return friends;
189         }
190
191         public List<Album> parseTopLevelAlbums(
192                         AlbumBuilderFactory albumBuilderFactory) {
193                 int albumCounter = 0;
194                 while (true) {
195                         String albumPrefix = "/Albums/" + albumCounter++;
196                         String albumId = getString(albumPrefix + "/ID", null);
197                         if (albumId == null) {
198                                 break;
199                         }
200                         String albumTitle = getString(albumPrefix + "/Title", null);
201                         String albumDescription =
202                                         getString(albumPrefix + "/Description", null);
203                         String albumParentId = getString(albumPrefix + "/Parent", null);
204                         String albumImageId =
205                                         getString(albumPrefix + "/AlbumImage", null);
206                         if ((albumTitle == null) || (albumDescription == null)) {
207                                 throw new InvalidAlbumFound();
208                         }
209                         Album album = albumBuilderFactory.newAlbumBuilder()
210                                         .withId(albumId)
211                                         .by(sone)
212                                         .build()
213                                         .modify()
214                                         .setTitle(albumTitle)
215                                         .setDescription(albumDescription)
216                                         .setAlbumImage(albumImageId)
217                                         .update();
218                         if (albumParentId != null) {
219                                 Album parentAlbum = albums.get(albumParentId);
220                                 if (parentAlbum == null) {
221                                         throw new InvalidParentAlbumFound(albumParentId);
222                                 }
223                                 parentAlbum.addAlbum(album);
224                         } else {
225                                 topLevelAlbums.add(album);
226                         }
227                         albums.put(albumId, album);
228                 }
229                 return topLevelAlbums;
230         }
231
232         public Map<String, Album> getAlbums() {
233                 return unmodifiableMap(albums);
234         }
235
236         public void parseImages(ImageBuilderFactory imageBuilderFactory) {
237                 int imageCounter = 0;
238                 while (true) {
239                         String imagePrefix = "/Images/" + imageCounter++;
240                         String imageId = getString(imagePrefix + "/ID", null);
241                         if (imageId == null) {
242                                 break;
243                         }
244                         String albumId = getString(imagePrefix + "/Album", null);
245                         String key = getString(imagePrefix + "/Key", null);
246                         String title = getString(imagePrefix + "/Title", null);
247                         String description =
248                                         getString(imagePrefix + "/Description", null);
249                         Long creationTime = getLong(imagePrefix + "/CreationTime", null);
250                         Integer width = getInt(imagePrefix + "/Width", null);
251                         Integer height = getInt(imagePrefix + "/Height", null);
252                         if (albumAttributesAreInvalid(albumId, key, title, description,
253                                         creationTime,
254                                         width, height)) {
255                                 throw new InvalidImageFound();
256                         }
257                         Album album = albums.get(albumId);
258                         if (album == null) {
259                                 throw new InvalidParentAlbumFound(albumId);
260                         }
261                         Image image = imageBuilderFactory.newImageBuilder()
262                                         .withId(imageId)
263                                         .build()
264                                         .modify()
265                                         .setSone(sone)
266                                         .setCreationTime(creationTime)
267                                         .setKey(key)
268                                         .setTitle(title)
269                                         .setDescription(description)
270                                         .setWidth(width)
271                                         .setHeight(height)
272                                         .update();
273                         album.addImage(image);
274                         images.put(image.getId(), image);
275                 }
276         }
277
278         public Map<String, Image> getImages() {
279                 return images;
280         }
281
282         private boolean albumAttributesAreInvalid(String albumId, String key,
283                         String title, String description, Long creationTime,
284                         Integer width, Integer height) {
285                 return (albumId == null) || (key == null) || (title == null) || (
286                                 description == null) || (creationTime == null) || (width
287                                 == null) || (height == null);
288         }
289
290         public static class InvalidPostFound extends RuntimeException { }
291
292         public static class InvalidPostReplyFound extends RuntimeException { }
293
294         public static class InvalidAlbumFound extends RuntimeException { }
295
296         public static class InvalidParentAlbumFound extends RuntimeException {
297
298                 private final String albumParentId;
299
300                 public InvalidParentAlbumFound(String albumParentId) {
301                         this.albumParentId = albumParentId;
302                 }
303
304                 public String getAlbumParentId() {
305                         return albumParentId;
306                 }
307
308         }
309
310         public static class InvalidImageFound extends RuntimeException { }
311
312 }