/*
* Copyright 2014 Gleb Godonoga.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.andrada.sitracker.loader;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.net.Uri;
import com.andrada.sitracker.contracts.AppUriContract;
import com.andrada.sitracker.db.beans.SearchedAuthor;
import com.andrada.sitracker.exceptions.SearchException;
import com.andrada.sitracker.reader.SamlibCgiSearchStrategyImpl;
import com.andrada.sitracker.reader.SamlibSeekSearchStrategyImpl;
import com.andrada.sitracker.reader.SearchStrategy;
import com.github.kevinsawicki.http.HttpRequest;
import org.jetbrains.annotations.NotNull;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import static com.andrada.sitracker.util.LogUtils.LOGD;
import static com.andrada.sitracker.util.LogUtils.LOGE;
public class SamlibSearchLoader extends AsyncTaskLoader<AsyncTaskResult<List<SearchedAuthor>>> {
public static final int SEARCH_TOKEN = 0x3;
private static final String TAG = "SamlibSearchLoader";
private SearchStrategy mSearchStrategy;
private List<SearchedAuthor> mAuthors = new ArrayList<SearchedAuthor>();
private Uri mQuery;
public SamlibSearchLoader(Context context, Uri query) {
super(context);
mQuery = query;
}
/**
* Called when there is new data to deliver to the client. The
* super class will take care of delivering it; the implementation
* here just adds a little more logic.
*/
@Override
public void deliverResult(@NotNull AsyncTaskResult<List<SearchedAuthor>> result) {
if (isReset()) {
// An async query came in while the loader is stopped. We
// don't need the result.
if (result.getResult().size() != 0) {
onReleaseResources(result.getResult());
}
}
List<SearchedAuthor> oldAuthors = mAuthors;
mAuthors = result.getResult();
if (isStarted()) {
// If the Loader is currently started, we can immediately
// deliver its results.
super.deliverResult(result);
}
// At this point we can release the resources associated with
// 'oldApps' if needed; now that the new result is delivered we
// know that it is no longer in use.
if (mAuthors.size() != 0) {
onReleaseResources(oldAuthors);
}
}
/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
if (mAuthors.size() != 0) {
// If we currently have a result available, deliver it
// immediately.
deliverResult(new AsyncTaskResult<List<SearchedAuthor>>(mAuthors, null));
}
if (takeContentChanged() || mAuthors.size() == 0) {
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
@Override
protected void onStopLoading() {
// Force cancel the current load task.
LOGD(TAG, "Force stopping task");
//Sanity
if (mSearchStrategy != null) {
mSearchStrategy.cancelAnyRunningTasks();
}
cancelLoad();
}
/**
* Handles a request to completely reset the Loader.
*/
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'apps'
// if needed.
if (mAuthors.size() != 0) {
onReleaseResources(null);
}
}
/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(AsyncTaskResult<List<SearchedAuthor>> result) {
super.onCanceled(result);
if (mSearchStrategy != null) {
mSearchStrategy.cancelAnyRunningTasks();
}
// if needed.
onReleaseResources(result.getResult());
}
@Override
public AsyncTaskResult<List<SearchedAuthor>> loadInBackground() {
int searchType = AppUriContract.getSearchTypeParam(mQuery);
Exception possibleException = null;
try {
if (searchType == 0) {
mSearchStrategy = new SamlibCgiSearchStrategyImpl();
} else {
mSearchStrategy = new SamlibSeekSearchStrategyImpl();
}
mAuthors.addAll(mSearchStrategy.searchForQuery(mQuery));
} catch (MalformedURLException e) {
possibleException = new SearchException(SearchException.SearchErrors.ERROR_UNKNOWN);
LOGE(TAG, "Got 404", e);
} catch (HttpRequest.HttpRequestException e) {
possibleException = new SearchException(SearchException.SearchErrors.NETWORK_ERROR);
LOGE(TAG, "Error reading stream", e);
} catch (SearchException e) {
possibleException = e;
LOGE(TAG, "Samlib server is busy", e);
} catch (InterruptedException e) {
possibleException = new SearchException(SearchException.SearchErrors.INTERNAL_ERROR);
LOGE(TAG, "Got thread interrupt", e);
}
return new AsyncTaskResult<List<SearchedAuthor>>(mAuthors, possibleException);
}
/**
* Helper function to take care of releasing resources associated
* with an actively loaded data set.
*/
protected void onReleaseResources(List<SearchedAuthor> result) {
// For a simple List<> there is nothing to do. For something
// like a Cursor, we would close it here.
mAuthors.clear();
}
}