aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java
blob: 8e4b11471789092622e28bb36148250fe8a4ab6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package cgeo.geocaching.loaders;

import cgeo.geocaching.SearchResult;
import cgeo.geocaching.connector.gc.GCConstants;
import cgeo.geocaching.connector.gc.RecaptchaHandler;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.TextUtils;

import org.apache.commons.lang3.StringUtils;

import android.content.Context;
import android.os.Handler;
import android.support.v4.content.AsyncTaskLoader;

import java.util.concurrent.CountDownLatch;

public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> implements RecaptchaReceiver {

    public enum CacheListLoaderType {
        OFFLINE,
        POCKET,
        HISTORY,
        NEAREST,
        COORDINATE,
        KEYWORD,
        ADDRESS,
        FINDER,
        OWNER,
        MAP,
        NEXT_PAGE;

        public int getLoaderId() {
            return ordinal();
        }
    }

    private Handler recaptchaHandler = null;
    private String recaptchaChallenge = null;
    private String recaptchaKey = null;
    private String recaptchaText = null;
    private SearchResult search;
    private boolean loading;
    private final CountDownLatch latch = new CountDownLatch(1);

    public AbstractSearchLoader(final Context context) {
        super(context);
    }

    public abstract SearchResult runSearch();

    public boolean isLoading() {
        return loading;
    }

    @Override
    public SearchResult loadInBackground() {
        loading = true;
        try {
            if (search == null) {
                search = runSearch();
            } else {
                // Unless we make a new Search the Loader framework won't deliver results. It does't do equals only identity
                search = new SearchResult(search);
            }
        } catch (final Exception e) {
            Log.e("Error in Loader ", e);
        }
        loading = false;
        if (search == null) {
            search = new SearchResult();
        }
        return search;
    }

    @Override
    protected void onStartLoading() {
        forceLoad();
    }

    public void setRecaptchaHandler(final Handler recaptchaHandler) {
        this.recaptchaHandler = recaptchaHandler;
    }

    @Override
    public void notifyNeed() {
        if (recaptchaHandler != null) {
            recaptchaHandler.sendEmptyMessage(RecaptchaHandler.SHOW_CAPTCHA);
        }
    }

    @Override
    public void waitForUser() {
        try {
            latch.await();
        } catch (final InterruptedException ignored) {
            Log.w("searchThread is not waiting for user…");
        }
    }

    @Override
    public void setKey(final String key) {
        recaptchaKey = key;
    }

    @Override
    public void fetchChallenge() {
        recaptchaChallenge = null;

        if (StringUtils.isNotEmpty(recaptchaKey)) {
            final Parameters params = new Parameters("k", recaptchaKey);
            final String recaptchaJs = Network.getResponseData(Network.getRequest("http://www.google.com/recaptcha/api/challenge", params));

            if (StringUtils.isNotBlank(recaptchaJs)) {
                recaptchaChallenge = TextUtils.getMatch(recaptchaJs, GCConstants.PATTERN_SEARCH_RECAPTCHACHALLENGE, true, 1, null, true);
            }
        }
    }

    @Override
    public String getChallenge() {
        return recaptchaChallenge;
    }

    @Override
    public void setText(final String text) {
        recaptchaText = text;
        latch.countDown();
    }

    @Override
    public String getText() {
        return recaptchaText;
    }

    @Override
    public void reset() {
        super.reset();
        search = null;
    }
}