Skip to content

Commit 9206e78

Browse files
bvibberGerrit Code Review
authored and
Gerrit Code Review
committed
Merge "Extract and show license key"
2 parents e0e3d21 + 4c45c88 commit 9206e78

File tree

11 files changed

+440
-4
lines changed

11 files changed

+440
-4
lines changed

commons/res/layout/detail_main_panel.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131
android:text="Description of the media goes here. This can potentially be fairly long, and will need to wrap across multiple lines. We hope it looks nice though."
3232
android:id="@+id/mediaDetailDesc"
3333
android:layout_gravity="left|start"/>
34+
<TextView
35+
android:layout_width="wrap_content"
36+
android:layout_height="wrap_content"
37+
android:text="License link"
38+
android:id="@+id/mediaDetailLicense"
39+
android:layout_gravity="left|start"
40+
android:textColor="@android:color/white"
41+
android:textSize="18sp" /> <!-- 18sp == MediumText -->
3442
<TextView
3543
android:layout_width="wrap_content"
3644
android:layout_height="wrap_content"

commons/res/values/strings.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,42 @@
9393
<string name="menu_download">Download</string>
9494
<string name="preference_license">License</string>
9595

96+
<!-- These three are semi-legacy entries, and should be changed in future -->
9697
<string name="license_name_cc_by_sa">CC\u00A0Attribution-ShareAlike\u00A03.0</string>
9798
<string name="license_name_cc_by">CC\u00A0Attribution\u00A03.0</string>
9899
<string name="license_name_cc0">CC0</string>
100+
101+
<!-- Licenses from the default UploadWizard selection list -->
102+
<string name="license_name_cc_by_sa_3_0">CC BY-SA 3.0</string>
103+
<string name="license_name_cc_by_sa_3_0_at">CC BY-SA 3.0 (Austria)</string>
104+
<string name="license_name_cc_by_sa_3_0_de">CC BY-SA 3.0 (Germany)</string>
105+
<string name="license_name_cc_by_sa_3_0_ee">CC BY-SA 3.0 (Estonia)</string>
106+
<string name="license_name_cc_by_sa_3_0_es">CC BY-SA 3.0 (Spain)</string>
107+
<string name="license_name_cc_by_sa_3_0_hr">CC BY-SA 3.0 (Croatia)</string>
108+
<string name="license_name_cc_by_sa_3_0_lu">CC BY-SA 3.0 (Luxembourg)</string>
109+
<string name="license_name_cc_by_sa_3_0_nl">CC BY-SA 3.0 (Netherlands)</string>
110+
<string name="license_name_cc_by_sa_3_0_no">CC BY-SA 3.0 (Norway)</string>
111+
<string name="license_name_cc_by_sa_3_0_pl">CC BY-SA 3.0 (Poland)</string>
112+
<string name="license_name_cc_by_sa_3_0_ro">CC BY-SA 3.0 (Romania)</string>
113+
<string name="license_name_cc_by_3_0">CC BY 3.0</string>
114+
<string name="license_name_cc_zero">CC Zero</string>
115+
<string name="license_name_own_pd">own-pd</string>
116+
<string name="license_name_cc_by_sa_2_5">CC BY-SA 2.5</string>
117+
<string name="license_name_cc_by_2_5">CC BY 2.5</string>
118+
<string name="license_name_cc_by_sa_2_0">CC BY-SA 2.0</string>
119+
<string name="license_name_cc_by_2_0">CC BY-SA 2.0</string>
120+
<string name="license_name_cc_2_0">CC BY 2.0</string>
121+
<string name="license_name_fal">Free Art License</string>
122+
<string name="license_name_pd_old_100">Public domain (author died over 100 years ago)</string>
123+
<string name="license_name_pd_old">Public domain (copyright expired)</string>
124+
<string name="license_name_pd_art">Public domain (art)</string>
125+
<string name="license_name_pd_us">Public domain (US)</string>
126+
<string name="license_name_pd_usgov">Public domain (US government)</string>
127+
<string name="license_name_pd_usgov_nasa">Public domain (NASA)</string>
128+
<string name="license_name_pd_ineligible">Public domain (ineligible for copyright)</string>
129+
<string name="license_name_attribution">Attribution</string>
130+
<string name="license_name_gfdl">GNU Free Documentation License</string>
131+
99132
<string name="welcome_wikipedia_text">Contribute your images. Help Wikipedia articles come to life!</string>
100133
<string name="welcome_wikipedia_subtext">Images on Wikipedia come from Wikimedia Commons.</string>
101134
<string name="welcome_copyright_text">Your images help educate people around the world.</string>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<licenses xmlns="https://www.mediawiki.org/wiki/Extension:UploadWizard/xmlns/licenses">
3+
<license id="cc-by-sa-3.0" template="cc-by-sa-3.0" url="https://creativecommons.org/licenses/by-sa/3.0/deed.$lang"/>
4+
<license id="cc-by-sa-3.0-at" template="cc-by-sa-3.0-at" url="https://creativecommons.org/licenses/by-sa/3.0/at/deed.$lang"/>
5+
<license id="cc-by-sa-3.0-de" template="cc-by-sa-3.0-de" url="https://creativecommons.org/licenses/by-sa/3.0/de/deed.$lang"/>
6+
<license id="cc-by-sa-3.0-ee" template="cc-by-sa-3.0-ee" url="https://creativecommons.org/licenses/by-sa/3.0/ee/deed.$lang"/>
7+
<license id="cc-by-sa-3.0-es" template="cc-by-sa-3.0-es" url="https://creativecommons.org/licenses/by-sa/3.0/es/deed.$lang"/>
8+
<license id="cc-by-sa-3.0-hr" template="cc-by-sa-3.0-hr" url="https://creativecommons.org/licenses/by-sa/3.0/hr/deed.$lang"/>
9+
<license id="cc-by-sa-3.0-lu" template="cc-by-sa-3.0-lu" url="https://creativecommons.org/licenses/by-sa/3.0/lu/deed.$lang"/>
10+
<license id="cc-by-sa-3.0-nl" template="cc-by-sa-3.0-nl" url="https://creativecommons.org/licenses/by-sa/3.0/nl/deed.$lang"/>
11+
<license id="cc-by-sa-3.0-no" template="cc-by-sa-3.0-no" url="https://creativecommons.org/licenses/by-sa/3.0/no/deed.$lang"/>
12+
<license id="cc-by-sa-3.0-pl" template="cc-by-sa-3.0-pl" url="https://creativecommons.org/licenses/by-sa/3.0/pl/deed.$lang"/>
13+
<license id="cc-by-sa-3.0-ro" template="cc-by-sa-3.0-ro" url="https://creativecommons.org/licenses/by-sa/3.0/ro/deed.$lang"/>
14+
<license id="cc-by-3.0" template="cc-by-3.0" url="https://creativecommons.org/licenses/by/3.0/deed.$lang"/>
15+
<license id="cc-zero" template="cc-zero" url="https://creativecommons.org/publicdomain/zero/1.0/deed.$lang"/>
16+
<license id="own-pd" template="cc-zero"/>
17+
<license id="cc-by-sa-2.5" template="cc-by-sa-2.5" url="https://creativecommons.org/licenses/by-sa/2.5/deed.$lang"/>
18+
<license id="cc-by-2.5" template="cc-by-2.5" url="https://creativecommons.org/licenses/by/2.5/deed.$lang"/>
19+
<license id="cc-by-sa-2.0" template="cc-by-sa-2.0" url="https://creativecommons.org/licenses/by-sa/2.0/deed.$lang"/>
20+
<license id="cc-by-2.0" template="cc-by-2.0" url="https://creativecommons.org/licenses/by/2.0/deed.$lang"/>
21+
<license id="fal" template="FAL"/>
22+
<license id="pd-old-100" template="PD-old-100"/>
23+
<license id="pd-old" template="PD-old"/>
24+
<license id="pd-art" template="PD-Art"/>
25+
<license id="pd-us" template="PD-US"/>
26+
<license id="pd-usgov" template="PD-USGov"/>
27+
<license id="pd-usgov-nasa" template="PD-USGov-NASA"/>
28+
<license id="pd-ineligible" template="pd-ineligible"/>
29+
<license id="attribution" template="attribution"/>
30+
<license id="gfdl" template="GFDL"/>
31+
</licenses>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.wikimedia.commons;
2+
3+
public class License {
4+
String key;
5+
String template;
6+
String url;
7+
String name;
8+
9+
public License(String key, String template, String url, String name) {
10+
if (key == null) {
11+
throw new RuntimeException("License.key must not be null");
12+
}
13+
if (template == null) {
14+
throw new RuntimeException("License.template must not be null");
15+
}
16+
this.key = key;
17+
this.template = template;
18+
this.url = url;
19+
this.name = name;
20+
}
21+
22+
public String getKey() {
23+
return key;
24+
}
25+
26+
public String getTemplate() {
27+
return template;
28+
}
29+
30+
public String getName() {
31+
if (name == null) {
32+
// hack
33+
return getKey();
34+
} else {
35+
return name;
36+
}
37+
}
38+
39+
public String getUrl(String language) {
40+
if (url == null) {
41+
return null;
42+
} else {
43+
return url.replace("$lang", language);
44+
}
45+
}
46+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.wikimedia.commons;
2+
3+
import android.app.Activity;
4+
import android.content.res.Resources;
5+
import android.util.Log;
6+
import org.xmlpull.v1.XmlPullParser;
7+
8+
import java.util.Collection;
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
import java.util.Set;
12+
13+
public class LicenseList {
14+
Map<String, License> licenses = new HashMap<String, License>();
15+
Resources res;
16+
17+
private static String XMLNS_LICENSE = "https://www.mediawiki.org/wiki/Extension:UploadWizard/xmlns/licenses";
18+
19+
public LicenseList(Activity activity) {
20+
res = activity.getResources();
21+
XmlPullParser parser = res.getXml(R.xml.wikimedia_licenses);
22+
while (Utils.xmlFastForward(parser, XMLNS_LICENSE, "license")) {
23+
String id = parser.getAttributeValue(null, "id");
24+
String template = parser.getAttributeValue(null, "template");
25+
String url = parser.getAttributeValue(null, "url");
26+
String name = nameForTemplate(template);
27+
License license = new License(id, template, url, name);
28+
licenses.put(id, license);
29+
}
30+
31+
}
32+
33+
public Set<String> keySet() {
34+
return licenses.keySet();
35+
}
36+
37+
public Collection<License> values() {
38+
return licenses.values();
39+
}
40+
41+
public License get(String key) {
42+
return licenses.get(key);
43+
}
44+
45+
public License licenseForTemplate(String template) {
46+
String ucTemplate = Utils.capitalize(template);
47+
for (License license : values()) {
48+
if (ucTemplate.equals(Utils.capitalize(license.getTemplate()))) {
49+
return license;
50+
}
51+
}
52+
return null;
53+
}
54+
55+
public String nameIdForTemplate(String template) {
56+
// hack :D
57+
// cc-by-sa-3.0 -> cc_by_sa_3_0
58+
return "license_name_" + template.toLowerCase().replace("-", "_").replace(".", "_");
59+
}
60+
61+
private int stringIdByName(String stringId) {
62+
return res.getIdentifier("org.wikimedia.commons:string/" + stringId, null, null);
63+
}
64+
65+
public String nameForTemplate(String template) {
66+
Log.d("Commons", "LicenseList.nameForTemplate: template: " + template);
67+
String stringId = nameIdForTemplate(template);
68+
Log.d("Commons", "LicenseList.nameForTemplate: stringId: " + stringId);
69+
int nameId = stringIdByName(stringId);
70+
Log.d("Commons", "LicenseList.nameForTemplate: nameId: " + nameId);
71+
String name = res.getString(nameId);
72+
Log.d("Commons", "LicenseList.nameForTemplate: name: " + name);
73+
return name;
74+
}
75+
}

commons/src/main/java/org/wikimedia/commons/MediaDataExtractor.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,19 @@ public class MediaDataExtractor {
3333
private Map<String, String> descriptions;
3434
private String author;
3535
private Date date;
36+
private String license;
37+
private LicenseList licenseList;
3638

3739
/**
3840
* @param filename of the target media object, should include 'File:' prefix
3941
*/
40-
public MediaDataExtractor(String filename) {
42+
public MediaDataExtractor(String filename, LicenseList licenseList) {
4143
this.filename = filename;
4244
categories = new ArrayList<String>();
4345
descriptions = new HashMap<String, String>();
4446
fetched = false;
4547
processed = false;
48+
this.licenseList = licenseList;
4649
}
4750

4851
/**
@@ -114,7 +117,41 @@ private void processWikiParseTree(String source) throws IOException {
114117
descriptions = getMultilingualText(descriptionNode);
115118

116119
Node authorNode = findTemplateParameter(templateNode, "author");
117-
author = Utils.getStringFromDOM(authorNode);
120+
author = getFlatText(authorNode);
121+
}
122+
123+
/*
124+
Pull up the license data list...
125+
look for the templates in two ways:
126+
* look for 'self' template and check its first parameter
127+
* if none, look for any of the known templates
128+
*/
129+
Log.d("Commons", "MediaDataExtractor searching for license");
130+
Node selfLicenseNode = findTemplate(doc.getDocumentElement(), "self");
131+
if (selfLicenseNode != null) {
132+
Node firstNode = findTemplateParameter(selfLicenseNode, 1);
133+
String licenseTemplate = getFlatText(firstNode);
134+
License license = licenseList.licenseForTemplate(licenseTemplate);
135+
if (license == null) {
136+
Log.d("Commons", "MediaDataExtractor found no matching license for self parameter: " + licenseTemplate + "; faking it");
137+
this.license = licenseTemplate; // hack hack! For non-selectable licenses that are still in the system.
138+
} else {
139+
// fixme: record the self-ness in here too... sigh
140+
// all this needs better server-side metadata
141+
this.license = license.getKey();
142+
Log.d("Commons", "MediaDataExtractor found self-license " + this.license);
143+
}
144+
} else {
145+
for (License license : licenseList.values()) {
146+
String templateName = license.getTemplate();
147+
Node template = findTemplate(doc.getDocumentElement(), templateName);
148+
if (template != null) {
149+
// Found!
150+
this.license = license.getKey();
151+
Log.d("Commons", "MediaDataExtractor found non-self license " + this.license);
152+
break;
153+
}
154+
}
118155
}
119156
}
120157

@@ -201,6 +238,10 @@ private Node findTemplateParameter(Node templateNode, TemplateChildNodeComparato
201238
throw new IOException("No matching template parameter node found.");
202239
}
203240

241+
private String getFlatText(Node parentNode) throws IOException {
242+
return parentNode.getTextContent();
243+
}
244+
204245
// Extract a dictionary of multilingual texts from a subset of the parse tree.
205246
// Texts are wrapped in things like {{en|foo} or {{en|1=foo bar}}.
206247
// Text outside those wrappers is stuffed into a 'default' faux language key if present.
@@ -246,6 +287,9 @@ public void fill(Media media) {
246287

247288
media.setCategories(categories);
248289
media.setDescriptions(descriptions);
290+
if (license != null) {
291+
media.setLicense(license);
292+
}
249293

250294
// add author, date, etc fields
251295
}

commons/src/main/java/org/wikimedia/commons/Utils.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import org.apache.commons.codec.digest.DigestUtils;
1111
import org.apache.commons.codec.net.URLCodec;
1212
import org.w3c.dom.Node;
13+
import org.xmlpull.v1.XmlPullParser;
14+
import org.xmlpull.v1.XmlPullParserException;
1315

1416
import javax.xml.transform.*;
1517
import java.io.*;
@@ -194,4 +196,33 @@ public static Uri uriForWikiPage(String name) {
194196
String uriStr = CommonsApplication.HOME_URL + urlEncode(underscored);
195197
return Uri.parse(uriStr);
196198
}
199+
200+
/**
201+
* Fast-forward an XmlPullParser to the next instance of the given element
202+
* in the input stream (namespaced).
203+
*
204+
* @param parser
205+
* @param namespace
206+
* @param element
207+
* @return true on match, false on failure
208+
*/
209+
public static boolean xmlFastForward(XmlPullParser parser, String namespace, String element) {
210+
try {
211+
while (parser.next() != XmlPullParser.END_DOCUMENT) {
212+
if (parser.getEventType() == XmlPullParser.START_TAG &&
213+
parser.getNamespace().equals(namespace) &&
214+
parser.getName().equals(element)) {
215+
// We found it!
216+
return true;
217+
}
218+
}
219+
return false;
220+
} catch (XmlPullParserException e) {
221+
e.printStackTrace();
222+
return false;
223+
} catch (IOException e) {
224+
e.printStackTrace();
225+
return false;
226+
}
227+
}
197228
}

commons/src/main/java/org/wikimedia/commons/media/MediaDetailFragment.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static MediaDetailFragment forMedia(int index, boolean editable) {
5959

6060
private TextView title;
6161
private TextView desc;
62+
private TextView license;
6263
private ListView listView;
6364
private ArrayList<String> categoryNames;
6465
private boolean categoriesLoaded = false;
@@ -133,6 +134,7 @@ public void onItemClick(AdapterView<?> adapterView, View view, int position, lon
133134
spacer = (MediaDetailSpacer) detailView.findViewById(R.id.mediaDetailSpacer);
134135
title = (TextView) detailView.findViewById(R.id.mediaDetailTitle);
135136
desc = (TextView) detailView.findViewById(R.id.mediaDetailDesc);
137+
license = (TextView) detailView.findViewById(R.id.mediaDetailLicense);
136138

137139
// Enable or disable editing on the title
138140
/*
@@ -160,10 +162,12 @@ public void onItemClick(AdapterView<?> adapterView, View view, int position, lon
160162
// FIXME: cache this data
161163
detailFetchTask = new AsyncTask<Void, Void, Boolean>() {
162164
private MediaDataExtractor extractor;
165+
private LicenseList licenseList;
163166

164167
@Override
165168
protected void onPreExecute() {
166-
extractor = new MediaDataExtractor(media.getFilename());
169+
licenseList = new LicenseList(getActivity());
170+
extractor = new MediaDataExtractor(media.getFilename(), licenseList);
167171
}
168172

169173
@Override
@@ -187,6 +191,16 @@ protected void onPostExecute(Boolean success) {
187191
// Fill some fields
188192
desc.setText(media.getDescription("en"));
189193

194+
String licenseKey = media.getLicense();
195+
License licenseObj = licenseList.get(licenseKey);
196+
if (licenseObj == null) {
197+
license.setText(licenseKey);
198+
} else {
199+
license.setText(licenseObj.getName());
200+
}
201+
Log.d("Commons", "Media license is: " + media.getLicense());
202+
203+
190204
categoryNames.removeAll(categoryNames);
191205
categoryNames.addAll(media.getCategories());
192206

@@ -231,7 +245,8 @@ public void onLoadingCancelled(String s, View view) {
231245
}
232246

233247
title.setText(media.getDisplayTitle());
234-
desc.setText("");
248+
desc.setText(""); // fill in from network...
249+
license.setText(""); // fill in from network...
235250

236251
/*
237252
title.addTextChangedListener(new TextWatcher() {

0 commit comments

Comments
 (0)