Skip to content

Commit c45b945

Browse files
maskaravivekashishkumar468
authored andcommitted
Use JSON APIs for explore (commons-app#2731)
* Use JSON APIs for explore * With tests * Use JSON APIs for explore * With tests * BugFix commons-app#2731 (#4) * Increased sdk version to 23 * with more robust tests * Fix crashes and other reported issues * Add javadocs * Use common method for search and categories * Add javadocs
1 parent c1a941e commit c45b945

14 files changed

+468
-318
lines changed

app/src/main/java/fr/free/nrw/commons/Media.java

+40-6
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
import android.net.Uri;
44
import android.os.Parcel;
55
import android.os.Parcelable;
6-
import androidx.annotation.Nullable;
76

87
import java.util.ArrayList;
8+
import java.util.Collections;
99
import java.util.Date;
1010
import java.util.HashMap;
1111
import java.util.List;
12+
import java.util.Locale;
1213
import java.util.Map;
1314
import java.util.regex.Matcher;
1415
import java.util.regex.Pattern;
1516

17+
import androidx.annotation.Nullable;
1618
import fr.free.nrw.commons.location.LatLng;
19+
import fr.free.nrw.commons.media.model.ExtMetadata;
1720
import fr.free.nrw.commons.media.model.ImageInfo;
1821
import fr.free.nrw.commons.media.model.MwQueryPage;
1922
import fr.free.nrw.commons.utils.DateUtils;
23+
import fr.free.nrw.commons.utils.MediaDataExtractorUtil;
2024
import fr.free.nrw.commons.utils.StringUtils;
2125

2226
public class Media implements Parcelable {
@@ -93,6 +97,8 @@ public Media(Uri localUri, String imageUrl, String filename, String description,
9397
this.dateCreated = dateCreated;
9498
this.dateUploaded = dateUploaded;
9599
this.creator = creator;
100+
this.categories = new ArrayList<>();
101+
this.descriptions = new HashMap<>();
96102
}
97103

98104
@SuppressWarnings("unchecked")
@@ -450,23 +456,51 @@ public boolean getRequestedDeletion(){
450456
return requestedDeletion;
451457
}
452458

459+
/**
460+
* Creating Media object from MWQueryPage.
461+
* Earlier only basic details were set for the media object but going forward,
462+
* a full media object(with categories, descriptions, coordinates etc) can be constructed using this method
463+
*
464+
* @param page response from the API
465+
* @return Media object
466+
*/
467+
@Nullable
453468
public static Media from(MwQueryPage page) {
454469
ImageInfo imageInfo = page.imageInfo();
455470
if(imageInfo == null) {
456471
return null;
457472
}
473+
ExtMetadata metadata = imageInfo.getMetadata();
474+
if (metadata == null) {
475+
return new Media(null, imageInfo.getOriginalUrl(),
476+
page.title(), "", 0, null, null, null);
477+
}
478+
458479
Media media = new Media(null,
459480
imageInfo.getOriginalUrl(),
460481
page.title(),
461-
imageInfo.getMetadata().imageDescription().value(),
482+
"",
462483
0,
463-
DateUtils.getDateFromString(imageInfo.getMetadata().dateTimeOriginal().value()),
464-
DateUtils.getDateFromString(imageInfo.getMetadata().dateTime().value()),
465-
StringUtils.getParsedStringFromHtml(imageInfo.getMetadata().artist().value())
484+
DateUtils.getDateFromString(metadata.dateTimeOriginal().value()),
485+
DateUtils.getDateFromString(metadata.dateTime().value()),
486+
StringUtils.getParsedStringFromHtml(metadata.artist().value())
466487
);
467488

468-
media.setLicense(imageInfo.getMetadata().licenseShortName().value());
489+
String language = Locale.getDefault().getLanguage();
490+
if (StringUtils.isNullOrWhiteSpace(language)) {
491+
language = "default";
492+
}
493+
media.setDescriptions(Collections.singletonMap(language, metadata.imageDescription().value()));
494+
media.setCategories(MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories().value()));
495+
String latitude = metadata.gpsLatitude().value();
496+
String longitude = metadata.gpsLongitude().value();
497+
498+
if(!StringUtils.isNullOrWhiteSpace(latitude) && !StringUtils.isNullOrWhiteSpace(longitude)) {
499+
LatLng latLng = new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude), 0);
500+
media.setCoordinates(latLng);
501+
}
469502

503+
media.setLicense(metadata.licenseShortName().value());
470504
return media;
471505
}
472506
}

app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ List<Media> loadBookmarkedPictures() {
3636
ArrayList<Media> medias = new ArrayList<>();
3737
for (Bookmark bookmark : bookmarks) {
3838
List<Media> tmpMedias = okHttpJsonApiClient
39-
.searchImages(bookmark.getMediaName(), 0)
39+
.getMediaList("search", bookmark.getMediaName())
4040
.blockingGet();
4141
for (Media m : tmpMedias) {
4242
if (m.getCreator().trim().equals(bookmark.getMediaCreator().trim())) {

app/src/main/java/fr/free/nrw/commons/category/CategoryImageController.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@
66
import javax.inject.Singleton;
77

88
import fr.free.nrw.commons.Media;
9-
import fr.free.nrw.commons.mwapi.MediaWikiApi;
9+
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
10+
import io.reactivex.Single;
1011

1112
@Singleton
1213
public class CategoryImageController {
1314

14-
private MediaWikiApi mediaWikiApi;
15+
private OkHttpJsonApiClient okHttpJsonApiClient;
1516

1617
@Inject
17-
public CategoryImageController(MediaWikiApi mediaWikiApi) {
18-
this.mediaWikiApi = mediaWikiApi;
18+
public CategoryImageController(OkHttpJsonApiClient okHttpJsonApiClient) {
19+
this.okHttpJsonApiClient = okHttpJsonApiClient;
1920
}
2021

2122
/**
2223
* Takes a category name as input and calls the API to get a list of images for that category
2324
* @param categoryName
2425
* @return
2526
*/
26-
public List<Media> getCategoryImages(String categoryName) {
27-
return mediaWikiApi.getCategoryImages(categoryName);
27+
public Single<List<Media>> getCategoryImages(String categoryName) {
28+
return okHttpJsonApiClient.getMediaList("category", categoryName);
2829
}
2930
}
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,15 @@
11
package fr.free.nrw.commons.category;
22

3-
import androidx.annotation.NonNull;
4-
53
import org.w3c.dom.Element;
64
import org.w3c.dom.Node;
75
import org.w3c.dom.NodeList;
86

9-
import java.text.ParseException;
10-
import java.text.SimpleDateFormat;
117
import java.util.ArrayList;
128
import java.util.Collections;
13-
import java.util.Date;
149
import java.util.List;
1510

16-
import javax.annotation.Nullable;
17-
18-
import fr.free.nrw.commons.Media;
19-
import fr.free.nrw.commons.utils.StringUtils;
20-
import timber.log.Timber;
21-
2211
public class CategoryImageUtils {
2312

24-
/**
25-
* The method iterates over the child nodes to return a list of Media objects
26-
* @param childNodes
27-
* @return
28-
*/
29-
public static List<Media> getMediaList(NodeList childNodes) {
30-
List<Media> categoryImages = new ArrayList<>();
31-
32-
for (int i = 0; i < childNodes.getLength(); i++) {
33-
Node node = childNodes.item(i);
34-
35-
if (getFileName(node).substring(0, 5).equals("File:")) {
36-
categoryImages.add(getMediaFromPage(node));
37-
}
38-
}
39-
40-
return categoryImages;
41-
}
42-
4313
/**
4414
* The method iterates over the child nodes to return a list of Subcategory name
4515
* sorted alphabetically
@@ -56,27 +26,6 @@ public static List<String> getSubCategoryList(NodeList childNodes) {
5626
return subCategories;
5727
}
5828

59-
/**
60-
* Creates a new Media object from the XML response as received by the API
61-
* @param node
62-
* @return
63-
*/
64-
public static Media getMediaFromPage(Node node) {
65-
Media media = new Media(null,
66-
getImageUrl(node),
67-
getFileName(node),
68-
getDescription(node),
69-
getDataLength(node),
70-
getDateCreated(node),
71-
getDateCreated(node),
72-
getCreator(node)
73-
);
74-
75-
media.setLicense(getLicense(node));
76-
77-
return media;
78-
}
79-
8029
/**
8130
* Extracts the filename of the uploaded image
8231
* @param document
@@ -87,162 +36,4 @@ private static String getFileName(Node document) {
8736
return element.getAttribute("title");
8837
}
8938

90-
/**
91-
* Extracts the image description for that particular upload
92-
* @param document
93-
* @return
94-
*/
95-
private static String getDescription(Node document) {
96-
return getMetaDataValue(document, "ImageDescription");
97-
}
98-
99-
/**
100-
* Extracts license information from the image meta data
101-
* @param document
102-
* @return
103-
*/
104-
private static String getLicense(Node document) {
105-
return getMetaDataValue(document, "License");
106-
}
107-
108-
/**
109-
* Returns the parsed value of artist from the response
110-
* The artist information is returned as a HTML string from the API. Using HTML parser to parse the HTML
111-
* @param document
112-
* @return
113-
*/
114-
@NonNull
115-
private static String getCreator(Node document) {
116-
String artist = getMetaDataValue(document, "Artist");
117-
if (StringUtils.isNullOrWhiteSpace(artist)) {
118-
return "";
119-
}
120-
return StringUtils.getParsedStringFromHtml(artist);
121-
}
122-
123-
/**
124-
* Returns the parsed date of creation of the image
125-
* @param document
126-
* @return
127-
*/
128-
private static Date getDateCreated(Node document) {
129-
String dateTime = getMetaDataValue(document, "DateTime");
130-
if (dateTime != null && !dateTime.equals("")) {
131-
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
132-
try {
133-
return format.parse(dateTime);
134-
} catch (ParseException e) {
135-
Timber.d("Error occurred while parsing date %s", dateTime);
136-
return new Date();
137-
}
138-
}
139-
return new Date();
140-
}
141-
142-
/**
143-
* @param document
144-
* @return Returns the url attribute from the imageInfo node
145-
*/
146-
private static String getImageUrl(Node document) {
147-
Element element = (Element) getImageInfo(document);
148-
if (element != null) {
149-
return element.getAttribute("url");
150-
}
151-
return null;
152-
}
153-
154-
/**
155-
* Takes the node document and gives out the attribute length from the node document
156-
* @param document
157-
* @return
158-
*/
159-
private static long getDataLength(Node document) {
160-
Element element = (Element) document;
161-
if (element != null) {
162-
String length = element.getAttribute("length");
163-
if (length != null && !length.equals("")) {
164-
return Long.parseLong(length);
165-
}
166-
}
167-
return 0L;
168-
}
169-
170-
/**
171-
* Generic method to get the value of any meta as returned by the getMetaData function
172-
* @param document node document as returned by API
173-
* @param metaName the name of meta node to be returned
174-
* @return
175-
*/
176-
private static String getMetaDataValue(Node document, String metaName) {
177-
Element metaData = getMetaData(document, metaName);
178-
if (metaData != null) {
179-
return metaData.getAttribute("value");
180-
}
181-
return null;
182-
}
183-
184-
/**
185-
* Generic method to return an element taking the node document and metaName as input
186-
* @param document node document as returned by API
187-
* @param metaName the name of meta node to be returned
188-
* @return
189-
*/
190-
@Nullable
191-
private static Element getMetaData(Node document, String metaName) {
192-
Node extraMetaData = getExtraMetaData(document);
193-
if (extraMetaData != null) {
194-
Node node = getNode(extraMetaData, metaName);
195-
if (node != null) {
196-
return (Element) node;
197-
}
198-
}
199-
return null;
200-
}
201-
202-
/**
203-
* Extracts extmetadata from the response XML
204-
* @param document
205-
* @return
206-
*/
207-
@Nullable
208-
private static Node getExtraMetaData(Node document) {
209-
Node imageInfo = getImageInfo(document);
210-
if (imageInfo != null) {
211-
return getNode(imageInfo, "extmetadata");
212-
}
213-
return null;
214-
}
215-
216-
/**
217-
* Extracts the ii node from the imageinfo node
218-
* @param document
219-
* @return
220-
*/
221-
@Nullable
222-
private static Node getImageInfo(Node document) {
223-
Node imageInfo = getNode(document, "imageinfo");
224-
if (imageInfo != null) {
225-
return getNode(imageInfo, "ii");
226-
}
227-
return null;
228-
}
229-
230-
/**
231-
* Takes a parent node as input and returns a child node if present
232-
* @param node parent node
233-
* @param nodeName child node name
234-
* @return
235-
*/
236-
@Nullable
237-
public static Node getNode(Node node, String nodeName) {
238-
NodeList childNodes = node.getChildNodes();
239-
for (int i = 0; i < childNodes.getLength(); i++) {
240-
Node nodeItem = childNodes.item(i);
241-
Element item = (Element) nodeItem;
242-
if (item.getTagName().equals(nodeName)) {
243-
return nodeItem;
244-
}
245-
}
246-
return null;
247-
}
24839
}

0 commit comments

Comments
 (0)