Skip to content

Use JSON APIs for explore #2731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 26, 2019
46 changes: 40 additions & 6 deletions app/src/main/java/fr/free/nrw/commons/Media.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import androidx.annotation.Nullable;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.media.model.ExtMetadata;
import fr.free.nrw.commons.media.model.ImageInfo;
import fr.free.nrw.commons.media.model.MwQueryPage;
import fr.free.nrw.commons.utils.DateUtils;
import fr.free.nrw.commons.utils.MediaDataExtractorUtil;
import fr.free.nrw.commons.utils.StringUtils;

public class Media implements Parcelable {
Expand Down Expand Up @@ -93,6 +97,8 @@ public Media(Uri localUri, String imageUrl, String filename, String description,
this.dateCreated = dateCreated;
this.dateUploaded = dateUploaded;
this.creator = creator;
this.categories = new ArrayList<>();
this.descriptions = new HashMap<>();
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -450,23 +456,51 @@ public boolean getRequestedDeletion(){
return requestedDeletion;
}

/**
* Creating Media object from MWQueryPage.
* Earlier only basic details were set for the media object but going forward,
* a full media object(with categories, descriptions, coordinates etc) can be constructed using this method
*
* @param page response from the API
* @return Media object
*/
@Nullable
public static Media from(MwQueryPage page) {
ImageInfo imageInfo = page.imageInfo();
if(imageInfo == null) {
return null;
}
ExtMetadata metadata = imageInfo.getMetadata();
if (metadata == null) {
return new Media(null, imageInfo.getOriginalUrl(),
page.title(), "", 0, null, null, null);
}

Media media = new Media(null,
imageInfo.getOriginalUrl(),
page.title(),
imageInfo.getMetadata().imageDescription().value(),
"",
0,
DateUtils.getDateFromString(imageInfo.getMetadata().dateTimeOriginal().value()),
DateUtils.getDateFromString(imageInfo.getMetadata().dateTime().value()),
StringUtils.getParsedStringFromHtml(imageInfo.getMetadata().artist().value())
DateUtils.getDateFromString(metadata.dateTimeOriginal().value()),
DateUtils.getDateFromString(metadata.dateTime().value()),
StringUtils.getParsedStringFromHtml(metadata.artist().value())
);

media.setLicense(imageInfo.getMetadata().licenseShortName().value());
String language = Locale.getDefault().getLanguage();
if (StringUtils.isNullOrWhiteSpace(language)) {
language = "default";
}
media.setDescriptions(Collections.singletonMap(language, metadata.imageDescription().value()));
media.setCategories(MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories().value()));
String latitude = metadata.gpsLatitude().value();
String longitude = metadata.gpsLongitude().value();

if(!StringUtils.isNullOrWhiteSpace(latitude) && !StringUtils.isNullOrWhiteSpace(longitude)) {
LatLng latLng = new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude), 0);
media.setCoordinates(latLng);
}

media.setLicense(metadata.licenseShortName().value());
return media;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ List<Media> loadBookmarkedPictures() {
ArrayList<Media> medias = new ArrayList<>();
for (Bookmark bookmark : bookmarks) {
List<Media> tmpMedias = okHttpJsonApiClient
.searchImages(bookmark.getMediaName(), 0)
.getMediaList("search", bookmark.getMediaName())
.blockingGet();
for (Media m : tmpMedias) {
if (m.getCreator().trim().equals(bookmark.getMediaCreator().trim())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
import javax.inject.Singleton;

import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import io.reactivex.Single;

@Singleton
public class CategoryImageController {

private MediaWikiApi mediaWikiApi;
private OkHttpJsonApiClient okHttpJsonApiClient;

@Inject
public CategoryImageController(MediaWikiApi mediaWikiApi) {
this.mediaWikiApi = mediaWikiApi;
public CategoryImageController(OkHttpJsonApiClient okHttpJsonApiClient) {
this.okHttpJsonApiClient = okHttpJsonApiClient;
}

/**
* Takes a category name as input and calls the API to get a list of images for that category
* @param categoryName
* @return
*/
public List<Media> getCategoryImages(String categoryName) {
return mediaWikiApi.getCategoryImages(categoryName);
public Single<List<Media>> getCategoryImages(String categoryName) {
return okHttpJsonApiClient.getMediaList("category", categoryName);
}
}
209 changes: 0 additions & 209 deletions app/src/main/java/fr/free/nrw/commons/category/CategoryImageUtils.java
Original file line number Diff line number Diff line change
@@ -1,45 +1,15 @@
package fr.free.nrw.commons.category;

import androidx.annotation.NonNull;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.annotation.Nullable;

import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.utils.StringUtils;
import timber.log.Timber;

public class CategoryImageUtils {

/**
* The method iterates over the child nodes to return a list of Media objects
* @param childNodes
* @return
*/
public static List<Media> getMediaList(NodeList childNodes) {
List<Media> categoryImages = new ArrayList<>();

for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);

if (getFileName(node).substring(0, 5).equals("File:")) {
categoryImages.add(getMediaFromPage(node));
}
}

return categoryImages;
}

/**
* The method iterates over the child nodes to return a list of Subcategory name
* sorted alphabetically
Expand All @@ -56,27 +26,6 @@ public static List<String> getSubCategoryList(NodeList childNodes) {
return subCategories;
}

/**
* Creates a new Media object from the XML response as received by the API
* @param node
* @return
*/
public static Media getMediaFromPage(Node node) {
Media media = new Media(null,
getImageUrl(node),
getFileName(node),
getDescription(node),
getDataLength(node),
getDateCreated(node),
getDateCreated(node),
getCreator(node)
);

media.setLicense(getLicense(node));

return media;
}

/**
* Extracts the filename of the uploaded image
* @param document
Expand All @@ -87,162 +36,4 @@ private static String getFileName(Node document) {
return element.getAttribute("title");
}

/**
* Extracts the image description for that particular upload
* @param document
* @return
*/
private static String getDescription(Node document) {
return getMetaDataValue(document, "ImageDescription");
}

/**
* Extracts license information from the image meta data
* @param document
* @return
*/
private static String getLicense(Node document) {
return getMetaDataValue(document, "License");
}

/**
* Returns the parsed value of artist from the response
* The artist information is returned as a HTML string from the API. Using HTML parser to parse the HTML
* @param document
* @return
*/
@NonNull
private static String getCreator(Node document) {
String artist = getMetaDataValue(document, "Artist");
if (StringUtils.isNullOrWhiteSpace(artist)) {
return "";
}
return StringUtils.getParsedStringFromHtml(artist);
}

/**
* Returns the parsed date of creation of the image
* @param document
* @return
*/
private static Date getDateCreated(Node document) {
String dateTime = getMetaDataValue(document, "DateTime");
if (dateTime != null && !dateTime.equals("")) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return format.parse(dateTime);
} catch (ParseException e) {
Timber.d("Error occurred while parsing date %s", dateTime);
return new Date();
}
}
return new Date();
}

/**
* @param document
* @return Returns the url attribute from the imageInfo node
*/
private static String getImageUrl(Node document) {
Element element = (Element) getImageInfo(document);
if (element != null) {
return element.getAttribute("url");
}
return null;
}

/**
* Takes the node document and gives out the attribute length from the node document
* @param document
* @return
*/
private static long getDataLength(Node document) {
Element element = (Element) document;
if (element != null) {
String length = element.getAttribute("length");
if (length != null && !length.equals("")) {
return Long.parseLong(length);
}
}
return 0L;
}

/**
* Generic method to get the value of any meta as returned by the getMetaData function
* @param document node document as returned by API
* @param metaName the name of meta node to be returned
* @return
*/
private static String getMetaDataValue(Node document, String metaName) {
Element metaData = getMetaData(document, metaName);
if (metaData != null) {
return metaData.getAttribute("value");
}
return null;
}

/**
* Generic method to return an element taking the node document and metaName as input
* @param document node document as returned by API
* @param metaName the name of meta node to be returned
* @return
*/
@Nullable
private static Element getMetaData(Node document, String metaName) {
Node extraMetaData = getExtraMetaData(document);
if (extraMetaData != null) {
Node node = getNode(extraMetaData, metaName);
if (node != null) {
return (Element) node;
}
}
return null;
}

/**
* Extracts extmetadata from the response XML
* @param document
* @return
*/
@Nullable
private static Node getExtraMetaData(Node document) {
Node imageInfo = getImageInfo(document);
if (imageInfo != null) {
return getNode(imageInfo, "extmetadata");
}
return null;
}

/**
* Extracts the ii node from the imageinfo node
* @param document
* @return
*/
@Nullable
private static Node getImageInfo(Node document) {
Node imageInfo = getNode(document, "imageinfo");
if (imageInfo != null) {
return getNode(imageInfo, "ii");
}
return null;
}

/**
* Takes a parent node as input and returns a child node if present
* @param node parent node
* @param nodeName child node name
* @return
*/
@Nullable
public static Node getNode(Node node, String nodeName) {
NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node nodeItem = childNodes.item(i);
Element item = (Element) nodeItem;
if (item.getTagName().equals(nodeName)) {
return nodeItem;
}
}
return null;
}
}
Loading