Skip to content

Commit 443007b

Browse files
committed
#3664 Stop using JsonObject on StructuredData - remove usage in Media classes - remove from depicts client - create partial network models
1 parent 92d6848 commit 443007b

22 files changed

+531
-287
lines changed

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

+10-12
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
import androidx.annotation.Nullable;
88
import androidx.room.Entity;
99
import fr.free.nrw.commons.location.LatLng;
10+
import fr.free.nrw.commons.media.Depictions;
1011
import fr.free.nrw.commons.utils.CommonsDateUtil;
1112
import fr.free.nrw.commons.utils.MediaDataExtractorUtil;
1213
import java.text.ParseException;
1314
import java.util.ArrayList;
1415
import java.util.Date;
1516
import java.util.List;
1617
import java.util.Locale;
17-
import java.util.Map;
1818
import org.apache.commons.lang3.StringUtils;
1919
import org.wikipedia.dataclient.mwapi.MwQueryPage;
2020
import org.wikipedia.gallery.ExtMetadata;
@@ -56,7 +56,7 @@ public class Media implements Parcelable {
5656
* Depicts is a feature part of Structured data. Multiple Depictions can be added for an image just like categories.
5757
* However unlike categories depictions is multi-lingual
5858
*/
59-
private List<Map<String, String>> depictionList= new ArrayList<>();
59+
private Depictions depictions;
6060
private boolean requestedDeletion;
6161
@Nullable private LatLng coordinates;
6262

@@ -305,12 +305,10 @@ public String getCaption() {
305305
/**
306306
* @return depictions associated with the current media
307307
*/
308-
public List<Map<String, String>> getDepiction() {
309-
return depictionList;
308+
public Depictions getDepiction() {
309+
return depictions;
310310
}
311311

312-
313-
314312
/**
315313
* Sets the file description.
316314
* @param description the new description of the file
@@ -489,8 +487,8 @@ public void setCaption(String caption) {
489487
}
490488

491489
/* Sets depictions for the current media obtained fro Wikibase API*/
492-
public void setDepictionList(List<Map<String, String>> depictions) {
493-
this.depictionList = depictions;
490+
public void setDepictions(Depictions depictions) {
491+
this.depictions = depictions;
494492
}
495493

496494
public void setLocalUri(@Nullable final Uri localUri) {
@@ -509,8 +507,8 @@ public void setLicenseUrl(final String licenseUrl) {
509507
this.licenseUrl = licenseUrl;
510508
}
511509

512-
public List<Map<String, String>> getDepictionList() {
513-
return depictionList;
510+
public Depictions getDepictions() {
511+
return depictions;
514512
}
515513

516514
@Override
@@ -542,7 +540,7 @@ public void writeToParcel(Parcel dest, int flags) {
542540
dest.writeString(this.creator);
543541
dest.writeString(this.pageId);
544542
dest.writeStringList(this.categories);
545-
dest.writeList(this.depictionList);
543+
dest.writeParcelable(this.depictions, flags);
546544
dest.writeByte(this.requestedDeletion ? (byte) 1 : (byte) 0);
547545
dest.writeParcelable(this.coordinates, flags);
548546
}
@@ -568,7 +566,7 @@ protected Media(Parcel in) {
568566
final ArrayList<String> list = new ArrayList<>();
569567
in.readStringList(list);
570568
this.categories=list;
571-
in.readList(depictionList,null);
569+
in.readParcelable(Depictions.class.getClassLoader());
572570
this.requestedDeletion = in.readByte() != 0;
573571
this.coordinates = in.readParcelable(LatLng.class.getClassLoader());
574572
}

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

+7-42
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
import static fr.free.nrw.commons.depictions.Media.DepictedImagesFragment.PAGE_ID_PREFIX;
44

55
import androidx.core.text.HtmlCompat;
6-
import com.google.gson.JsonArray;
7-
import com.google.gson.JsonObject;
6+
import fr.free.nrw.commons.media.Depictions;
87
import fr.free.nrw.commons.media.MediaClient;
98
import io.reactivex.Single;
10-
import java.util.ArrayList;
11-
import java.util.HashMap;
12-
import java.util.Map;
139
import javax.inject.Inject;
1410
import javax.inject.Singleton;
1511
import org.jetbrains.annotations.NotNull;
@@ -24,10 +20,6 @@
2420
@Singleton
2521
public class MediaDataExtractor {
2622

27-
private static final int LABEL_BEGIN_INDEX = 3;
28-
private static final int LABEL_END_OFFSET = 3;
29-
private static final int ID_BEGIN_INDEX = 1;
30-
private static final int ID_END_OFFSET = 1;
3123
private final MediaClient mediaClient;
3224

3325
@Inject
@@ -52,10 +44,10 @@ public Single<Media> fetchMediaDetails(final String filename, final String pageI
5244

5345
@NotNull
5446
private Media combineToMedia(final Media media, final Boolean deletionStatus, final String discussion,
55-
final String caption, final JsonObject depiction) {
47+
final String caption, final Depictions depictions) {
5648
media.setDiscussion(discussion);
5749
media.setCaption(caption);
58-
media.setDepictionList(formatDepictions(depiction));
50+
media.setDepictions(depictions);
5951
if (deletionStatus) {
6052
media.setRequestedDeletion(true);
6153
}
@@ -74,39 +66,12 @@ private Single<String> getCaption(final String wikibaseIdentifier) {
7466
}
7567

7668
/**
77-
* From the Json Object extract depictions into an array list
78-
* @param mediaResponse
79-
* @return List containing map for depictions, the map has two keys,
80-
* first key is for the label and second is for the url of the item
81-
*/
82-
private ArrayList<Map<String, String>> formatDepictions(final JsonObject mediaResponse) {
83-
try {
84-
final JsonArray depictionArray = (JsonArray) mediaResponse.get("Depiction");
85-
final ArrayList<Map<String, String>> depictedItemList = new ArrayList<>();
86-
for (int i = 0; i <depictionArray.size() ; i++) {
87-
final JsonObject depictedItem = (JsonObject) depictionArray.get(i);
88-
final Map <String, String> depictedObject = new HashMap<>();
89-
final String label = depictedItem.get("label").toString();
90-
final String id = depictedItem.get("id").toString();
91-
final String transformedLabel = label.substring(LABEL_BEGIN_INDEX, label.length()- LABEL_END_OFFSET);
92-
final String transformedId = id.substring(ID_BEGIN_INDEX,id.length() - ID_END_OFFSET);
93-
depictedObject.put("label", transformedLabel); //remove the additional characters obtained in label and ID object to extract the relevant string (since the string also contains extra quites that are not required)
94-
depictedObject.put("id", transformedId);
95-
depictedItemList.add(depictedObject);
96-
}
97-
return depictedItemList;
98-
} catch (final ClassCastException | NullPointerException ignore) {
99-
return new ArrayList<>();
100-
}
101-
}
102-
103-
/**
104-
* Fetch caption and depictions from the MediaWiki API
69+
* Fetch depictions from the MediaWiki API
10570
* @param filename the filename we will return the caption for
106-
* @return a map containing caption and depictions (empty string in the map if no caption/depictions)
71+
* @return Depictions
10772
*/
108-
private Single<JsonObject> getDepictions(final String filename) {
109-
return mediaClient.getCaptionAndDepictions(filename)
73+
private Single<Depictions> getDepictions(final String filename) {
74+
return mediaClient.getDepictions(filename)
11075
.doOnError(throwable -> Timber.e(throwable, "error while fetching depictions"));
11176
}
11277

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private static OkHttpClient createClient() {
4141

4242
private static HttpLoggingInterceptor getLoggingInterceptor() {
4343
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor()
44-
.setLevel(Level.BASIC);
44+
.setLevel(Level.BODY);
4545

4646
httpLoggingInterceptor.redactHeader("Authorization");
4747
httpLoggingInterceptor.redactHeader("Cookie");

app/src/main/java/fr/free/nrw/commons/db/Converters.java

+11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import fr.free.nrw.commons.CommonsApplication;
88
import fr.free.nrw.commons.di.ApplicationlessInjection;
99
import fr.free.nrw.commons.location.LatLng;
10+
import fr.free.nrw.commons.media.Depictions;
1011
import fr.free.nrw.commons.upload.WikidataPlace;
1112
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
1213
import java.util.Date;
@@ -102,6 +103,16 @@ public static List<DepictedItem> stringToList(String depictedItems) {
102103
return readObjectWithTypeToken(depictedItems, new TypeToken<List<DepictedItem>>() {});
103104
}
104105

106+
@TypeConverter
107+
public static String aptionsAndDepictionsToString(Depictions depictedItems) {
108+
return writeObjectToString(depictedItems);
109+
}
110+
111+
@TypeConverter
112+
public static Depictions stringToCaptionsAndDepictions(String depictedItems) {
113+
return readObjectFromString(depictedItems, Depictions.class);
114+
}
115+
105116
private static String writeObjectToString(Object object) {
106117
return object == null ? null : getGson().toJson(object);
107118
}

app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.java

+25-34
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package fr.free.nrw.commons.explore.depictions;
22

33
import androidx.annotation.Nullable;
4-
5-
import com.google.gson.JsonObject;
6-
import com.google.gson.JsonPrimitive;
7-
8-
4+
import fr.free.nrw.commons.BuildConfig;
5+
import fr.free.nrw.commons.Media;
6+
import fr.free.nrw.commons.depictions.models.Search;
7+
import fr.free.nrw.commons.media.MediaInterface;
8+
import fr.free.nrw.commons.upload.depicts.DepictsInterface;
9+
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
10+
import fr.free.nrw.commons.utils.CommonsDateUtil;
11+
import fr.free.nrw.commons.wikidata.WikidataProperties;
12+
import io.reactivex.Observable;
13+
import io.reactivex.Single;
914
import java.math.BigInteger;
1015
import java.security.MessageDigest;
1116
import java.security.NoSuchAlgorithmException;
@@ -14,19 +19,10 @@
1419
import java.util.Date;
1520
import java.util.List;
1621
import java.util.Locale;
17-
1822
import javax.inject.Inject;
1923
import javax.inject.Singleton;
20-
21-
import fr.free.nrw.commons.BuildConfig;
22-
import fr.free.nrw.commons.Media;
23-
import fr.free.nrw.commons.depictions.models.Search;
24-
import fr.free.nrw.commons.media.MediaInterface;
25-
import fr.free.nrw.commons.upload.depicts.DepictsInterface;
26-
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
27-
import fr.free.nrw.commons.utils.CommonsDateUtil;
28-
import io.reactivex.Observable;
29-
import io.reactivex.Single;
24+
import org.wikipedia.wikidata.DataValue_partial.DataValueString_partial;
25+
import org.wikipedia.wikidata.Statement_partial;
3026

3127
/**
3228
* Depicts Client to handle custom calls to Commons Wikibase APIs
@@ -81,24 +77,19 @@ private String getThumbnailUrl(String title) {
8177
*/
8278
public Single<String> getP18ForItem(String entityId) {
8379
return depictsInterface.getImageForEntity(entityId)
84-
.map(commonsFilename -> {
85-
String name;
86-
try {
87-
JsonObject claims = commonsFilename.getAsJsonObject("claims").getAsJsonObject();
88-
JsonObject p18 = claims.get("P18").getAsJsonArray().get(0).getAsJsonObject();
89-
JsonObject mainsnak = p18.get("mainsnak").getAsJsonObject();
90-
JsonObject datavalue = mainsnak.get("datavalue").getAsJsonObject();
91-
JsonPrimitive value = datavalue.get("value").getAsJsonPrimitive();
92-
name = value.toString();
93-
name = name.substring(1, name.length() - 1);
94-
} catch (Exception e) {
95-
name="";
96-
}
97-
if (!name.isEmpty()){
98-
return getThumbnailUrl(name);
99-
} else return NO_DEPICTED_IMAGE;
100-
})
101-
.singleOrError();
80+
.map(claimsResponse -> {
81+
final List<Statement_partial> imageClaim = claimsResponse.getClaims()
82+
.get(WikidataProperties.IMAGE.getPropertyName());
83+
if (imageClaim != null) {
84+
final DataValueString_partial dataValue = (DataValueString_partial) imageClaim
85+
.get(0)
86+
.getMainSnak()
87+
.getDataValue();
88+
return getThumbnailUrl((dataValue.getValue()));
89+
}
90+
return NO_DEPICTED_IMAGE;
91+
})
92+
.singleOrError();
10293
}
10394

10495
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package fr.free.nrw.commons.media
2+
3+
import android.os.Parcelable
4+
import androidx.annotation.WorkerThread
5+
import fr.free.nrw.commons.wikidata.WikidataProperties.DEPICTS
6+
import kotlinx.android.parcel.Parcelize
7+
import org.wikipedia.wikidata.DataValue_partial.DataValueEntityId_partial
8+
import org.wikipedia.wikidata.Entities
9+
import java.util.*
10+
11+
@Parcelize
12+
data class Depictions(val depictions: List<IdAndLabel>) : Parcelable {
13+
companion object {
14+
@JvmStatic
15+
@WorkerThread
16+
fun from(entities: Entities, mediaClient: MediaClient) =
17+
Depictions(
18+
entities.first?.statements
19+
?.getOrElse(DEPICTS.propertyName, { emptyList() })
20+
?.map { statement ->
21+
(statement.mainSnak.dataValue as DataValueEntityId_partial).value.id
22+
}
23+
?.map { id -> IdAndLabel(id, fetchLabel(mediaClient, id)) }
24+
?: emptyList()
25+
)
26+
27+
private fun fetchLabel(mediaClient: MediaClient, id: String) =
28+
mediaClient.getLabelForDepiction(id, Locale.getDefault().language).blockingGet()
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package fr.free.nrw.commons.media
2+
3+
import android.os.Parcelable
4+
import kotlinx.android.parcel.Parcelize
5+
import org.wikipedia.wikidata.Entities
6+
7+
@Parcelize
8+
data class IdAndLabel(val entityId: String, val entityLabel: String) : Parcelable {
9+
constructor(entityId: String, entities: MutableMap<String, Entities.Entity>) : this(
10+
entityId,
11+
entities.values.first().labels().values.first().value()
12+
)
13+
}
14+

0 commit comments

Comments
 (0)