mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-11-04 08:43:52 +01:00 
			
		
		
		
	Merge branch 'main' into fix-issues
This commit is contained in:
		
						commit
						7a932ef61f
					
				
					 8 changed files with 348 additions and 427 deletions
				
			
		| 
						 | 
				
			
			@ -105,7 +105,7 @@ class AboutActivityTest {
 | 
			
		|||
    fun testLaunchTranslate() {
 | 
			
		||||
        Espresso.onView(ViewMatchers.withId(R.id.about_translate)).perform(ViewActions.click())
 | 
			
		||||
        Espresso.onView(ViewMatchers.withId(android.R.id.button1)).perform(ViewActions.click())
 | 
			
		||||
        val langCode = CommonsApplication.instance.languageLookUpTable!!.codes[0]
 | 
			
		||||
        val langCode = CommonsApplication.instance.languageLookUpTable!!.getCodes()[0]
 | 
			
		||||
        Intents.intended(
 | 
			
		||||
            CoreMatchers.allOf(
 | 
			
		||||
                IntentMatchers.hasAction(Intent.ACTION_VIEW),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,6 @@ import okhttp3.logging.HttpLoggingInterceptor
 | 
			
		|||
import okhttp3.logging.HttpLoggingInterceptor.Level
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
import java.util.concurrent.TimeUnit
 | 
			
		||||
import javax.inject.Named
 | 
			
		||||
import javax.inject.Singleton
 | 
			
		||||
| 
						 | 
				
			
			@ -293,9 +292,8 @@ class NetworkingModule {
 | 
			
		|||
    @Provides
 | 
			
		||||
    @Singleton
 | 
			
		||||
    @Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE)
 | 
			
		||||
    fun provideLanguageWikipediaSite(): WikiSite {
 | 
			
		||||
        return WikiSite.forLanguageCode(Locale.getDefault().language)
 | 
			
		||||
    }
 | 
			
		||||
    fun provideLanguageWikipediaSite(): WikiSite =
 | 
			
		||||
        WikiSite.forDefaultLocaleLanguageCode()
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private const val WIKIDATA_SPARQL_QUERY_URL = "https://query.wikidata.org/sparql"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
package fr.free.nrw.commons.wikidata.model;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Model class for API response obtained from search for depictions
 | 
			
		||||
 */
 | 
			
		||||
public class DepictSearchResponse {
 | 
			
		||||
    private final List<DepictSearchItem> search;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor to initialise value of the search object
 | 
			
		||||
     */
 | 
			
		||||
    public DepictSearchResponse(List<DepictSearchItem> search) {
 | 
			
		||||
        this.search = search;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return List<DepictSearchItem> for the DepictSearchResponse
 | 
			
		||||
     */
 | 
			
		||||
    public List<DepictSearchItem> getSearch() {
 | 
			
		||||
        return search;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
package fr.free.nrw.commons.wikidata.model
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Model class for API response obtained from search for depictions
 | 
			
		||||
 */
 | 
			
		||||
class DepictSearchResponse(
 | 
			
		||||
    /**
 | 
			
		||||
     * @return List<DepictSearchItem> for the DepictSearchResponse
 | 
			
		||||
    </DepictSearchItem>
 | 
			
		||||
     */
 | 
			
		||||
    val search: List<DepictSearchItem>
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,106 +0,0 @@
 | 
			
		|||
package fr.free.nrw.commons.wikidata.model;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import com.google.gson.annotations.SerializedName;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
import fr.free.nrw.commons.wikidata.mwapi.MwResponse;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class Entities extends MwResponse {
 | 
			
		||||
    @Nullable private Map<String, Entity> entities;
 | 
			
		||||
    private int success;
 | 
			
		||||
 | 
			
		||||
    @NotNull
 | 
			
		||||
    public Map<String, Entity> entities() {
 | 
			
		||||
        return entities != null ? entities : Collections.emptyMap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getSuccess() {
 | 
			
		||||
        return success;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable public Entity getFirst() {
 | 
			
		||||
        if (entities == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        return entities.values().iterator().next();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void postProcess() {
 | 
			
		||||
        if (getFirst() != null && getFirst().isMissing()) {
 | 
			
		||||
            throw new RuntimeException("The requested entity was not found.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Entity {
 | 
			
		||||
        @Nullable private String type;
 | 
			
		||||
        @Nullable private String id;
 | 
			
		||||
        @Nullable private Map<String, Label> labels;
 | 
			
		||||
        @Nullable private Map<String, Label> descriptions;
 | 
			
		||||
        @Nullable private Map<String, SiteLink> sitelinks;
 | 
			
		||||
        @Nullable @SerializedName(value = "statements", alternate = "claims") private Map<String, List<StatementPartial>> statements;
 | 
			
		||||
        @Nullable private String missing;
 | 
			
		||||
 | 
			
		||||
        @NonNull public String id() {
 | 
			
		||||
            return StringUtils.defaultString(id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull public Map<String, Label> labels() {
 | 
			
		||||
            return labels != null ? labels : Collections.emptyMap();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull public Map<String, Label> descriptions() {
 | 
			
		||||
            return descriptions != null ? descriptions : Collections.emptyMap();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull public Map<String, SiteLink> sitelinks() {
 | 
			
		||||
            return sitelinks != null ? sitelinks : Collections.emptyMap();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nullable
 | 
			
		||||
        public Map<String, List<StatementPartial>> getStatements() {
 | 
			
		||||
            return statements;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        boolean isMissing() {
 | 
			
		||||
            return "-1".equals(id) && missing != null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Label {
 | 
			
		||||
        @Nullable private String language;
 | 
			
		||||
        @Nullable private String value;
 | 
			
		||||
 | 
			
		||||
        public Label(@Nullable final String language, @Nullable final String value) {
 | 
			
		||||
            this.language = language;
 | 
			
		||||
            this.value = value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull public String language() {
 | 
			
		||||
            return StringUtils.defaultString(language);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull public String value() {
 | 
			
		||||
            return StringUtils.defaultString(value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class SiteLink {
 | 
			
		||||
        @Nullable private String site;
 | 
			
		||||
        @Nullable private String title;
 | 
			
		||||
 | 
			
		||||
        @NonNull public String getSite() {
 | 
			
		||||
            return StringUtils.defaultString(site);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @NonNull public String getTitle() {
 | 
			
		||||
            return StringUtils.defaultString(title);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
package fr.free.nrw.commons.wikidata.model
 | 
			
		||||
 | 
			
		||||
import com.google.gson.annotations.SerializedName
 | 
			
		||||
import fr.free.nrw.commons.wikidata.mwapi.MwResponse
 | 
			
		||||
import org.apache.commons.lang3.StringUtils
 | 
			
		||||
 | 
			
		||||
class Entities : MwResponse() {
 | 
			
		||||
    private val entities: Map<String, Entity>? = null
 | 
			
		||||
    val success: Int = 0
 | 
			
		||||
 | 
			
		||||
    fun entities(): Map<String, Entity> = entities ?: emptyMap()
 | 
			
		||||
 | 
			
		||||
    private val first : Entity?
 | 
			
		||||
        get() = entities?.values?.iterator()?.next()
 | 
			
		||||
 | 
			
		||||
    override fun postProcess() {
 | 
			
		||||
        first?.let {
 | 
			
		||||
            if (it.isMissing()) throw RuntimeException("The requested entity was not found.")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class Entity {
 | 
			
		||||
        private val type: String? = null
 | 
			
		||||
        private val id: String? = null
 | 
			
		||||
        private val labels: Map<String, Label>? = null
 | 
			
		||||
        private val descriptions: Map<String, Label>? = null
 | 
			
		||||
        private val sitelinks: Map<String, SiteLink>? = null
 | 
			
		||||
 | 
			
		||||
        @SerializedName(value = "statements", alternate = ["claims"])
 | 
			
		||||
        val statements: Map<String, List<StatementPartial>>? = null
 | 
			
		||||
        private val missing: String? = null
 | 
			
		||||
 | 
			
		||||
        fun id(): String =
 | 
			
		||||
            StringUtils.defaultString(id)
 | 
			
		||||
 | 
			
		||||
        fun labels(): Map<String, Label> =
 | 
			
		||||
            labels ?: emptyMap()
 | 
			
		||||
 | 
			
		||||
        fun descriptions(): Map<String, Label> =
 | 
			
		||||
            descriptions ?: emptyMap()
 | 
			
		||||
 | 
			
		||||
        fun sitelinks(): Map<String, SiteLink> =
 | 
			
		||||
            sitelinks ?: emptyMap()
 | 
			
		||||
 | 
			
		||||
        fun isMissing(): Boolean =
 | 
			
		||||
            "-1" == id && missing != null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class Label(private val language: String?, private val value: String?) {
 | 
			
		||||
        fun language(): String =
 | 
			
		||||
            StringUtils.defaultString(language)
 | 
			
		||||
 | 
			
		||||
        fun value(): String =
 | 
			
		||||
            StringUtils.defaultString(value)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class SiteLink {
 | 
			
		||||
        val site: String? = null
 | 
			
		||||
            get() = StringUtils.defaultString(field)
 | 
			
		||||
 | 
			
		||||
        private val title: String? = null
 | 
			
		||||
            get() = StringUtils.defaultString(field)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,292 +0,0 @@
 | 
			
		|||
package fr.free.nrw.commons.wikidata.model;
 | 
			
		||||
 | 
			
		||||
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.apache.commons.lang3.StringUtils;
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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 {
 | 
			
		||||
    private static String WIKIPEDIA_URL = "https://wikipedia.org/";
 | 
			
		||||
 | 
			
		||||
    public static final String DEFAULT_SCHEME = "https";
 | 
			
		||||
    private static String DEFAULT_BASE_URL = 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 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 = getLanguageVariantFromUri(tempUri);
 | 
			
		||||
        if (!TextUtils.isEmpty(langVariant)) {
 | 
			
		||||
            languageCode = langVariant;
 | 
			
		||||
        } else {
 | 
			
		||||
            languageCode = authorityToLanguageCode(authority);
 | 
			
		||||
        }
 | 
			
		||||
        this.uri = new Uri.Builder()
 | 
			
		||||
                .scheme(tempUri.getScheme())
 | 
			
		||||
                .encodedAuthority(authority)
 | 
			
		||||
                .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Get language variant code from a Uri, e.g. "zh-*", otherwise returns empty string. */
 | 
			
		||||
    @NonNull
 | 
			
		||||
    private String getLanguageVariantFromUri(@NonNull Uri uri) {
 | 
			
		||||
        if (TextUtils.isEmpty(uri.getPath())) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        String[] parts = StringUtils.split(StringUtils.defaultString(uri.getPath()), '/');
 | 
			
		||||
        return parts.length > 1 && !parts[0].equals("wiki") ? parts[0] : "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get wiki's mobile URL
 | 
			
		||||
     * Eg. https://en.m.wikipedia.org
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    public String mobileUrl() {
 | 
			
		||||
        return String.format("%1$s://%2$s", scheme(), mobileAuthority());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										269
									
								
								app/src/main/java/fr/free/nrw/commons/wikidata/model/WikiSite.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								app/src/main/java/fr/free/nrw/commons/wikidata/model/WikiSite.kt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,269 @@
 | 
			
		|||
package fr.free.nrw.commons.wikidata.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Parcel
 | 
			
		||||
import android.os.Parcelable
 | 
			
		||||
import android.text.TextUtils
 | 
			
		||||
import com.google.gson.annotations.SerializedName
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.CHINESE_CN_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.CHINESE_HK_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.CHINESE_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.CHINESE_MO_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.CHINESE_SG_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.CHINESE_TW_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.NORWEGIAN_BOKMAL_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.NORWEGIAN_LEGACY_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.SIMPLIFIED_CHINESE_LANGUAGE_CODE
 | 
			
		||||
import fr.free.nrw.commons.language.AppLanguageLookUpTable.Companion.TRADITIONAL_CHINESE_LANGUAGE_CODE
 | 
			
		||||
import org.apache.commons.lang3.StringUtils
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The base URL and Wikipedia language code for a MediaWiki site. Examples:
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * <lh>Name: scheme / authority / language code</lh>
 | 
			
		||||
 *  * English Wikipedia: HTTPS / en.wikipedia.org / en
 | 
			
		||||
 *  * Chinese Wikipedia: HTTPS / zh.wikipedia.org / zh-hans or zh-hant
 | 
			
		||||
 *  * Meta-Wiki: HTTPS / meta.wikimedia.org / (none)
 | 
			
		||||
 *  * Test Wikipedia: HTTPS / test.wikipedia.org / test
 | 
			
		||||
 *  * Võro Wikipedia: HTTPS / fiu-vro.wikipedia.org / fiu-vro
 | 
			
		||||
 *  * Simple English Wikipedia: HTTPS / simple.wikipedia.org / simple
 | 
			
		||||
 *  * Simple English Wikipedia (beta cluster mirror): HTTP / simple.wikipedia.beta.wmflabs.org / simple
 | 
			
		||||
 *  * Development: HTTP / 192.168.1.11:8080 / (none)
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * **As shown above, the language code or mapping is part of the authority:**
 | 
			
		||||
 *
 | 
			
		||||
 * <lh>Validity: authority / language code</lh>
 | 
			
		||||
 *  * Correct: "test.wikipedia.org" / "test"
 | 
			
		||||
 *  * Correct: "wikipedia.org", ""
 | 
			
		||||
 *  * Correct: "no.wikipedia.org", "nb"
 | 
			
		||||
 *  * Incorrect: "wikipedia.org", "test"
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class WikiSite : Parcelable {
 | 
			
		||||
    //TODO: remove @SerializedName. this is now in the TypeAdapter and a "uri" case may be added
 | 
			
		||||
    @SerializedName("domain")
 | 
			
		||||
    private val uri: Uri
 | 
			
		||||
 | 
			
		||||
    private var languageCode: String? = null
 | 
			
		||||
 | 
			
		||||
    constructor(uri: Uri) {
 | 
			
		||||
        val tempUri = ensureScheme(uri)
 | 
			
		||||
        var authority = tempUri.authority
 | 
			
		||||
 | 
			
		||||
        if (authority.isWikipedia && tempUri.path?.startsWith("/wiki") == true) {
 | 
			
		||||
            // Special case for Wikipedia only: assume English subdomain when none given.
 | 
			
		||||
            authority = "en.wikipedia.org"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val langVariant = getLanguageVariantFromUri(tempUri)
 | 
			
		||||
        languageCode = if (!TextUtils.isEmpty(langVariant)) {
 | 
			
		||||
            langVariant
 | 
			
		||||
        } else {
 | 
			
		||||
            authorityToLanguageCode(authority!!)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.uri = Uri.Builder()
 | 
			
		||||
            .scheme(tempUri.scheme)
 | 
			
		||||
            .encodedAuthority(authority)
 | 
			
		||||
            .build()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val String?.isWikipedia: Boolean get() =
 | 
			
		||||
        (this == "wikipedia.org" || this == "www.wikipedia.org")
 | 
			
		||||
 | 
			
		||||
    /** Get language variant code from a Uri, e.g. "zh-*", otherwise returns empty string.  */
 | 
			
		||||
    private fun getLanguageVariantFromUri(uri: Uri): String {
 | 
			
		||||
        if (TextUtils.isEmpty(uri.path)) {
 | 
			
		||||
            return ""
 | 
			
		||||
        }
 | 
			
		||||
        val parts = StringUtils.split(StringUtils.defaultString(uri.path), '/')
 | 
			
		||||
        return if (parts.size > 1 && parts[0] != "wiki") parts[0] else ""
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor(url: String) : this(
 | 
			
		||||
        if (url.startsWith("http")) Uri.parse(url) else if (url.startsWith("//"))
 | 
			
		||||
            Uri.parse("$DEFAULT_SCHEME:$url")
 | 
			
		||||
        else
 | 
			
		||||
            Uri.parse("$DEFAULT_SCHEME://$url")
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    constructor(authority: String, languageCode: String) : this(authority) {
 | 
			
		||||
        this.languageCode = languageCode
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun scheme(): String =
 | 
			
		||||
        if (TextUtils.isEmpty(uri.scheme)) DEFAULT_SCHEME else uri.scheme!!
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return The complete wiki authority including language subdomain but not including scheme,
 | 
			
		||||
     * authentication, port, nor trailing slash.
 | 
			
		||||
     *
 | 
			
		||||
     * @see [URL syntax](https://en.wikipedia.org/wiki/Uniform_Resource_Locator.Syntax)
 | 
			
		||||
     */
 | 
			
		||||
    fun authority(): String = uri.authority!!
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Like [.authority] but with a "m." between the language subdomain and the rest of the host.
 | 
			
		||||
     * Examples:
 | 
			
		||||
     *
 | 
			
		||||
     *
 | 
			
		||||
     *  * English Wikipedia: en.m.wikipedia.org
 | 
			
		||||
     *  * Chinese Wikipedia: zh.m.wikipedia.org
 | 
			
		||||
     *  * Meta-Wiki: meta.m.wikimedia.org
 | 
			
		||||
     *  * Test Wikipedia: test.m.wikipedia.org
 | 
			
		||||
     *  * Võro Wikipedia: fiu-vro.m.wikipedia.org
 | 
			
		||||
     *  * Simple English Wikipedia: simple.m.wikipedia.org
 | 
			
		||||
     *  * Simple English Wikipedia (beta cluster mirror): simple.m.wikipedia.beta.wmflabs.org
 | 
			
		||||
     *  * Development: m.192.168.1.11
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    fun mobileAuthority(): String = authorityToMobile(authority())
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get wiki's mobile URL
 | 
			
		||||
     * Eg. https://en.m.wikipedia.org
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    fun mobileUrl(): String = String.format("%1\$s://%2\$s", scheme(), mobileAuthority())
 | 
			
		||||
 | 
			
		||||
    fun subdomain(): String = languageCodeToSubdomain(languageCode!!)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return A path without an authority for the segment including a leading "/".
 | 
			
		||||
     */
 | 
			
		||||
    fun path(segment: String): String = "/w/$segment"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    fun uri(): Uri = uri
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return The canonical URL. e.g., https://en.wikipedia.org.
 | 
			
		||||
     */
 | 
			
		||||
    fun url(): String = uri.toString()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return The canonical URL for segment. e.g., https://en.wikipedia.org/w/foo.
 | 
			
		||||
     */
 | 
			
		||||
    fun url(segment: String): String = 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
 | 
			
		||||
     */
 | 
			
		||||
    fun languageCode(): String = languageCode!!
 | 
			
		||||
 | 
			
		||||
    // Auto-generated
 | 
			
		||||
    override fun equals(o: Any?): Boolean {
 | 
			
		||||
        if (this === o) {
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
        if (o == null || javaClass != o.javaClass) {
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val wiki = o as WikiSite
 | 
			
		||||
 | 
			
		||||
        if (uri != wiki.uri) {
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
        return languageCode == wiki.languageCode
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Auto-generated
 | 
			
		||||
    override fun hashCode(): Int {
 | 
			
		||||
        var result = uri.hashCode()
 | 
			
		||||
        result = 31 * result + languageCode.hashCode()
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Auto-generated
 | 
			
		||||
    override fun toString(): String {
 | 
			
		||||
        return ("WikiSite{"
 | 
			
		||||
                + "uri=" + uri
 | 
			
		||||
                + ", languageCode='" + languageCode + '\''
 | 
			
		||||
                + '}')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun describeContents(): Int = 0
 | 
			
		||||
 | 
			
		||||
    override fun writeToParcel(dest: Parcel, flags: Int) {
 | 
			
		||||
        dest.writeParcelable(uri, 0)
 | 
			
		||||
        dest.writeString(languageCode)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected constructor(`in`: Parcel) {
 | 
			
		||||
        uri = `in`.readParcelable(Uri::class.java.classLoader)!!
 | 
			
		||||
        languageCode = `in`.readString()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** @param authority Host and optional port.
 | 
			
		||||
     */
 | 
			
		||||
    private fun authorityToMobile(authority: String): String {
 | 
			
		||||
        if (authority.startsWith("m.") || authority.contains(".m.")) {
 | 
			
		||||
            return authority
 | 
			
		||||
        }
 | 
			
		||||
        return authority.replaceFirst(("^" + subdomain() + "\\.?").toRegex(), "$0m.")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val WIKIPEDIA_URL = "https://wikipedia.org/"
 | 
			
		||||
        const val DEFAULT_SCHEME: String = "https"
 | 
			
		||||
 | 
			
		||||
        @JvmField
 | 
			
		||||
        val CREATOR: Parcelable.Creator<WikiSite> = object : Parcelable.Creator<WikiSite> {
 | 
			
		||||
            override fun createFromParcel(parcel: Parcel): WikiSite {
 | 
			
		||||
                return WikiSite(parcel)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            override fun newArray(size: Int): Array<WikiSite?> {
 | 
			
		||||
                return arrayOfNulls(size)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun forDefaultLocaleLanguageCode(): WikiSite {
 | 
			
		||||
            val languageCode: String = Locale.getDefault().language
 | 
			
		||||
            val subdomain = if (languageCode.isEmpty()) "" else languageCodeToSubdomain(languageCode) + "."
 | 
			
		||||
            val uri = ensureScheme(Uri.parse(WIKIPEDIA_URL))
 | 
			
		||||
            return WikiSite(subdomain + uri.authority, languageCode)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private fun languageCodeToSubdomain(languageCode: String): String = when (languageCode) {
 | 
			
		||||
            SIMPLIFIED_CHINESE_LANGUAGE_CODE,
 | 
			
		||||
            TRADITIONAL_CHINESE_LANGUAGE_CODE,
 | 
			
		||||
            CHINESE_CN_LANGUAGE_CODE,
 | 
			
		||||
            CHINESE_HK_LANGUAGE_CODE,
 | 
			
		||||
            CHINESE_MO_LANGUAGE_CODE,
 | 
			
		||||
            CHINESE_SG_LANGUAGE_CODE,
 | 
			
		||||
            CHINESE_TW_LANGUAGE_CODE -> CHINESE_LANGUAGE_CODE
 | 
			
		||||
 | 
			
		||||
            NORWEGIAN_BOKMAL_LANGUAGE_CODE -> NORWEGIAN_LEGACY_LANGUAGE_CODE // T114042
 | 
			
		||||
 | 
			
		||||
            else -> languageCode
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private fun authorityToLanguageCode(authority: String): String {
 | 
			
		||||
            val parts = authority.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
 | 
			
		||||
            val minLengthForSubdomain = 3
 | 
			
		||||
            if (parts.size < minLengthForSubdomain || parts.size == minLengthForSubdomain && parts[0] == "m") {
 | 
			
		||||
                // ""
 | 
			
		||||
                // wikipedia.org
 | 
			
		||||
                // m.wikipedia.org
 | 
			
		||||
                return ""
 | 
			
		||||
            }
 | 
			
		||||
            return parts[0]
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private fun ensureScheme(uri: Uri): Uri {
 | 
			
		||||
            if (TextUtils.isEmpty(uri.scheme)) {
 | 
			
		||||
                return uri.buildUpon().scheme(DEFAULT_SCHEME).build()
 | 
			
		||||
            }
 | 
			
		||||
            return uri
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue