mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
320 lines
11 KiB
Java
320 lines
11 KiB
Java
package org.wikipedia.dataclient;
|
|
|
|
import android.net.Uri;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.text.TextUtils;
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import com.google.gson.annotations.SerializedName;
|
|
|
|
import org.wikipedia.language.AppLanguageLookUpTable;
|
|
import org.wikipedia.page.PageTitle;
|
|
import org.wikipedia.util.UriUtil;
|
|
|
|
/**
|
|
* The base URL and Wikipedia language code for a MediaWiki site. Examples:
|
|
*
|
|
* <ul>
|
|
* <lh>Name: scheme / authority / language code</lh>
|
|
* <li>English Wikipedia: HTTPS / en.wikipedia.org / en</li>
|
|
* <li>Chinese Wikipedia: HTTPS / zh.wikipedia.org / zh-hans or zh-hant</li>
|
|
* <li>Meta-Wiki: HTTPS / meta.wikimedia.org / (none)</li>
|
|
* <li>Test Wikipedia: HTTPS / test.wikipedia.org / test</li>
|
|
* <li>Võro Wikipedia: HTTPS / fiu-vro.wikipedia.org / fiu-vro</li>
|
|
* <li>Simple English Wikipedia: HTTPS / simple.wikipedia.org / simple</li>
|
|
* <li>Simple English Wikipedia (beta cluster mirror): HTTP / simple.wikipedia.beta.wmflabs.org / simple</li>
|
|
* <li>Development: HTTP / 192.168.1.11:8080 / (none)</li>
|
|
* </ul>
|
|
*
|
|
* <strong>As shown above, the language code or mapping is part of the authority:</strong>
|
|
* <ul>
|
|
* <lh>Validity: authority / language code</lh>
|
|
* <li>Correct: "test.wikipedia.org" / "test"</li>
|
|
* <li>Correct: "wikipedia.org", ""</li>
|
|
* <li>Correct: "no.wikipedia.org", "nb"</li>
|
|
* <li>Incorrect: "wikipedia.org", "test"</li>
|
|
* </ul>
|
|
*/
|
|
public class WikiSite implements Parcelable {
|
|
public static final String DEFAULT_SCHEME = "https";
|
|
private static String DEFAULT_BASE_URL = Service.WIKIPEDIA_URL;
|
|
|
|
public static final Parcelable.Creator<WikiSite> CREATOR = new Parcelable.Creator<WikiSite>() {
|
|
@Override
|
|
public WikiSite createFromParcel(Parcel in) {
|
|
return new WikiSite(in);
|
|
}
|
|
|
|
@Override
|
|
public WikiSite[] newArray(int size) {
|
|
return new WikiSite[size];
|
|
}
|
|
};
|
|
|
|
// todo: remove @SerializedName. this is now in the TypeAdapter and a "uri" case may be added
|
|
@SerializedName("domain") @NonNull private final Uri uri;
|
|
@NonNull private String languageCode;
|
|
|
|
public static boolean supportedAuthority(@NonNull String authority) {
|
|
return authority.endsWith(Uri.parse(DEFAULT_BASE_URL).getAuthority());
|
|
}
|
|
|
|
public static void setDefaultBaseUrl(@NonNull String url) {
|
|
DEFAULT_BASE_URL = TextUtils.isEmpty(url) ? Service.WIKIPEDIA_URL : url;
|
|
}
|
|
|
|
public static WikiSite forLanguageCode(@NonNull String languageCode) {
|
|
Uri uri = ensureScheme(Uri.parse(DEFAULT_BASE_URL));
|
|
return new WikiSite((languageCode.isEmpty()
|
|
? "" : (languageCodeToSubdomain(languageCode) + ".")) + uri.getAuthority(),
|
|
languageCode);
|
|
}
|
|
|
|
public WikiSite(@NonNull Uri uri) {
|
|
Uri tempUri = ensureScheme(uri);
|
|
String authority = tempUri.getAuthority();
|
|
if (("wikipedia.org".equals(authority) || "www.wikipedia.org".equals(authority))
|
|
&& tempUri.getPath() != null && tempUri.getPath().startsWith("/wiki")) {
|
|
// Special case for Wikipedia only: assume English subdomain when none given.
|
|
authority = "en.wikipedia.org";
|
|
}
|
|
String langVariant = UriUtil.getLanguageVariantFromUri(tempUri);
|
|
if (!TextUtils.isEmpty(langVariant)) {
|
|
languageCode = langVariant;
|
|
} else {
|
|
languageCode = authorityToLanguageCode(authority);
|
|
}
|
|
this.uri = new Uri.Builder()
|
|
.scheme(tempUri.getScheme())
|
|
.encodedAuthority(authority)
|
|
.build();
|
|
}
|
|
|
|
public WikiSite(@NonNull String url) {
|
|
this(url.startsWith("http") ? Uri.parse(url) : url.startsWith("//")
|
|
? Uri.parse(DEFAULT_SCHEME + ":" + url) : Uri.parse(DEFAULT_SCHEME + "://" + url));
|
|
}
|
|
|
|
public WikiSite(@NonNull String authority, @NonNull String languageCode) {
|
|
this(authority);
|
|
this.languageCode = languageCode;
|
|
}
|
|
|
|
@NonNull
|
|
public String scheme() {
|
|
return TextUtils.isEmpty(uri.getScheme()) ? DEFAULT_SCHEME : uri.getScheme();
|
|
}
|
|
|
|
/**
|
|
* @return The complete wiki authority including language subdomain but not including scheme,
|
|
* authentication, port, nor trailing slash.
|
|
*
|
|
* @see <a href='https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax'>URL syntax</a>
|
|
*/
|
|
@NonNull
|
|
public String authority() {
|
|
return uri.getAuthority();
|
|
}
|
|
|
|
/**
|
|
* Like {@link #authority()} but with a "m." between the language subdomain and the rest of the host.
|
|
* Examples:
|
|
*
|
|
* <ul>
|
|
* <li>English Wikipedia: en.m.wikipedia.org</li>
|
|
* <li>Chinese Wikipedia: zh.m.wikipedia.org</li>
|
|
* <li>Meta-Wiki: meta.m.wikimedia.org</li>
|
|
* <li>Test Wikipedia: test.m.wikipedia.org</li>
|
|
* <li>Võro Wikipedia: fiu-vro.m.wikipedia.org</li>
|
|
* <li>Simple English Wikipedia: simple.m.wikipedia.org</li>
|
|
* <li>Simple English Wikipedia (beta cluster mirror): simple.m.wikipedia.beta.wmflabs.org</li>
|
|
* <li>Development: m.192.168.1.11</li>
|
|
* </ul>
|
|
*/
|
|
@NonNull
|
|
public String mobileAuthority() {
|
|
return authorityToMobile(authority());
|
|
}
|
|
|
|
/**
|
|
* @return The canonical "desktop" form of the authority. For example, if the authority
|
|
* is in a "mobile" form, e.g. en.m.wikipedia.org, this will become en.wikipedia.org.
|
|
*/
|
|
@NonNull
|
|
public String desktopAuthority() {
|
|
return authority().replace(".m.", ".");
|
|
}
|
|
|
|
@NonNull
|
|
public String subdomain() {
|
|
return languageCodeToSubdomain(languageCode);
|
|
}
|
|
|
|
/**
|
|
* @return A path without an authority for the segment including a leading "/".
|
|
*/
|
|
@NonNull
|
|
public String path(@NonNull String segment) {
|
|
return "/w/" + segment;
|
|
}
|
|
|
|
|
|
@NonNull public Uri uri() {
|
|
return uri;
|
|
}
|
|
|
|
/**
|
|
* @return The canonical URL. e.g., https://en.wikipedia.org.
|
|
*/
|
|
@NonNull public String url() {
|
|
return uri.toString();
|
|
}
|
|
|
|
/**
|
|
* @return The canonical URL for segment. e.g., https://en.wikipedia.org/w/foo.
|
|
*/
|
|
@NonNull public String url(@NonNull String segment) {
|
|
return url() + path(segment);
|
|
}
|
|
|
|
/**
|
|
* @return The wiki language code which may differ from the language subdomain. Empty if
|
|
* language code is unknown. Ex: "en", "zh-hans", ""
|
|
*
|
|
* @see AppLanguageLookUpTable
|
|
*/
|
|
@NonNull
|
|
public String languageCode() {
|
|
return languageCode;
|
|
}
|
|
|
|
// TODO: this method doesn't have much to do with WikiSite. Move to PageTitle?
|
|
/**
|
|
* Create a PageTitle object from an internal link string.
|
|
*
|
|
* @param internalLink Internal link target text (eg. /wiki/Target).
|
|
* Should be URL decoded before passing in
|
|
* @return A {@link PageTitle} object representing the internalLink passed in.
|
|
*/
|
|
public PageTitle titleForInternalLink(String internalLink) {
|
|
// Strip the /wiki/ from the href
|
|
return new PageTitle(UriUtil.removeInternalLinkPrefix(internalLink), this);
|
|
}
|
|
|
|
// TODO: this method doesn't have much to do with WikiSite. Move to PageTitle?
|
|
/**
|
|
* Create a PageTitle object from a Uri, taking into account any fragment (section title) in the link.
|
|
* @param uri Uri object to be turned into a PageTitle.
|
|
* @return {@link PageTitle} object that corresponds to the given Uri.
|
|
*/
|
|
public PageTitle titleForUri(Uri uri) {
|
|
String path = uri.getPath();
|
|
if (!TextUtils.isEmpty(uri.getFragment())) {
|
|
path += "#" + uri.getFragment();
|
|
}
|
|
return titleForInternalLink(path);
|
|
}
|
|
|
|
@NonNull public String dbName() {
|
|
return subdomain().replaceAll("-", "_") + "wiki";
|
|
}
|
|
|
|
// Auto-generated
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) {
|
|
return true;
|
|
}
|
|
if (o == null || getClass() != o.getClass()) {
|
|
return false;
|
|
}
|
|
|
|
WikiSite wiki = (WikiSite) o;
|
|
|
|
if (!uri.equals(wiki.uri)) {
|
|
return false;
|
|
}
|
|
return languageCode.equals(wiki.languageCode);
|
|
}
|
|
|
|
// Auto-generated
|
|
@Override
|
|
public int hashCode() {
|
|
int result = uri.hashCode();
|
|
result = 31 * result + languageCode.hashCode();
|
|
return result;
|
|
}
|
|
|
|
// Auto-generated
|
|
@Override
|
|
public String toString() {
|
|
return "WikiSite{"
|
|
+ "uri=" + uri
|
|
+ ", languageCode='" + languageCode + '\''
|
|
+ '}';
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
|
dest.writeParcelable(uri, 0);
|
|
dest.writeString(languageCode);
|
|
}
|
|
|
|
protected WikiSite(@NonNull Parcel in) {
|
|
this.uri = in.readParcelable(Uri.class.getClassLoader());
|
|
this.languageCode = in.readString();
|
|
}
|
|
|
|
@NonNull
|
|
private static String languageCodeToSubdomain(@NonNull String languageCode) {
|
|
switch (languageCode) {
|
|
case AppLanguageLookUpTable.SIMPLIFIED_CHINESE_LANGUAGE_CODE:
|
|
case AppLanguageLookUpTable.TRADITIONAL_CHINESE_LANGUAGE_CODE:
|
|
case AppLanguageLookUpTable.CHINESE_CN_LANGUAGE_CODE:
|
|
case AppLanguageLookUpTable.CHINESE_HK_LANGUAGE_CODE:
|
|
case AppLanguageLookUpTable.CHINESE_MO_LANGUAGE_CODE:
|
|
case AppLanguageLookUpTable.CHINESE_SG_LANGUAGE_CODE:
|
|
case AppLanguageLookUpTable.CHINESE_TW_LANGUAGE_CODE:
|
|
return AppLanguageLookUpTable.CHINESE_LANGUAGE_CODE;
|
|
case AppLanguageLookUpTable.NORWEGIAN_BOKMAL_LANGUAGE_CODE:
|
|
return AppLanguageLookUpTable.NORWEGIAN_LEGACY_LANGUAGE_CODE; // T114042
|
|
default:
|
|
return languageCode;
|
|
}
|
|
}
|
|
|
|
@NonNull private static String authorityToLanguageCode(@NonNull String authority) {
|
|
String[] parts = authority.split("\\.");
|
|
final int minLengthForSubdomain = 3;
|
|
if (parts.length < minLengthForSubdomain
|
|
|| parts.length == minLengthForSubdomain && parts[0].equals("m")) {
|
|
// ""
|
|
// wikipedia.org
|
|
// m.wikipedia.org
|
|
return "";
|
|
}
|
|
return parts[0];
|
|
}
|
|
|
|
@NonNull private static Uri ensureScheme(@NonNull Uri uri) {
|
|
if (TextUtils.isEmpty(uri.getScheme())) {
|
|
return uri.buildUpon().scheme(DEFAULT_SCHEME).build();
|
|
}
|
|
return uri;
|
|
}
|
|
|
|
/** @param authority Host and optional port. */
|
|
@NonNull private String authorityToMobile(@NonNull String authority) {
|
|
if (authority.startsWith("m.") || authority.contains(".m.")) {
|
|
return authority;
|
|
}
|
|
return authority.replaceFirst("^" + subdomain() + "\\.?", "$0m.");
|
|
}
|
|
}
|