com.andrada.sitracker.reader.Samlib.java Source code

Java tutorial

Introduction

Here is the source code for com.andrada.sitracker.reader.Samlib.java

Source

/*
 * 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.reader;

import android.util.Log;

import com.andrada.sitracker.Constants;
import com.andrada.sitracker.R;
import com.andrada.sitracker.db.beans.Author;
import com.andrada.sitracker.db.beans.Publication;
import com.andrada.sitracker.db.dao.AuthorDao;
import com.andrada.sitracker.db.dao.PublicationDao;
import com.andrada.sitracker.db.manager.SiDBHelper;
import com.andrada.sitracker.exceptions.AddAuthorException;
import com.andrada.sitracker.util.AnalyticsHelper;
import com.andrada.sitracker.util.LogUtils;
import com.andrada.sitracker.util.SamlibPageHelper;
import com.github.kevinsawicki.http.HttpRequest;
import com.j256.ormlite.dao.ForeignCollection;

import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Callable;

class Samlib implements SiteStrategy {

    private final SiDBHelper helper;

    public Samlib(SiDBHelper helper) {
        this.helper = helper;
    }

    @Override
    public int addAuthorForUrl(@NotNull String url) {
        Author author = null;
        int message = -1;
        try {
            if (url.equals("") || !url.matches(Constants.SIMPLE_URL_REGEX)) {
                throw new MalformedURLException();
            }
            url = url.replace("zhurnal.lib.ru", "samlib.ru");

            if (!url.endsWith(Constants.AUTHOR_PAGE_URL_ENDING_WO_SLASH)
                    && !url.endsWith(Constants.AUTHOR_PAGE_ALT_URL_ENDING_WO_SLASH)) {
                url = (url.endsWith("/")) ? url + Constants.AUTHOR_PAGE_URL_ENDING_WO_SLASH
                        : url + Constants.AUTHOR_PAGE_URL_ENDING_WI_SLASH;
            }

            if (!url.startsWith(Constants.HTTP_PROTOCOL) && !url.startsWith(Constants.HTTPS_PROTOCOL)) {
                url = Constants.HTTP_PROTOCOL + url;
            }
            String urlId = SamlibPageHelper.getUrlIdFromCompleteUrl(url);
            if (helper.getAuthorDao().queryBuilder().where().eq("urlId", urlId).query().size() != 0) {
                throw new AddAuthorException(AddAuthorException.AuthorAddErrors.AUTHOR_ALREADY_EXISTS);
            }

            HttpRequest request = HttpRequest.get(new URL(url));
            if (request.code() == 404) {
                throw new MalformedURLException();
            }
            AuthorPageReader reader = new SamlibAuthorPageReader(request.body());
            author = reader.getAuthor(url);
            helper.getAuthorDao().create(author);
            final List<Publication> items = reader.getPublications(author);
            if (items.size() == 0) {
                helper.getAuthorDao().delete(author);
                throw new AddAuthorException(AddAuthorException.AuthorAddErrors.AUTHOR_NO_PUBLICATIONS);
            }

            helper.getPublicationDao().callBatchTasks(new Callable<Object>() {
                @Nullable
                @Override
                public Object call() throws Exception {
                    for (Publication publication : items) {
                        helper.getPublicationDao().create(publication);
                    }
                    return null;
                }
            });

        } catch (HttpRequest.HttpRequestException e) {
            message = R.string.cannot_add_author_network;
        } catch (MalformedURLException e) {
            message = R.string.cannot_add_author_malformed;
        } catch (SQLException e) {
            if (author != null) {
                try {
                    helper.getAuthorDao().delete(author);
                } catch (SQLException e1) {
                    //Swallow the exception as the author just wasn't saved
                }
            }
            message = R.string.cannot_add_author_internal;
        } catch (AddAuthorException e) {
            switch (e.getError()) {
            case AUTHOR_ALREADY_EXISTS:
                message = R.string.cannot_add_author_already_exits;
                break;
            case AUTHOR_DATE_NOT_FOUND:
                message = R.string.cannot_add_author_no_update_date;
                break;
            case AUTHOR_NAME_NOT_FOUND:
                message = R.string.cannot_add_author_no_name;
                break;
            case AUTHOR_NO_PUBLICATIONS:
                message = R.string.cannot_add_author_no_publications;
                break;
            default:
                message = R.string.cannot_add_author_unknown;
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return message;
    }

    @Override
    public boolean updateAuthor(@NotNull Author author) throws SQLException {
        boolean authorUpdated = false;
        HttpRequest request;
        AuthorPageReader reader;
        try {
            URL authorURL = new URL(author.getUrl());
            request = HttpRequest.get(authorURL);
            if (request.code() == 404) {
                //skip this author
                //Not available atm
                return false;
            }
            if (!authorURL.getHost().equals(request.url().getHost())) {
                //We are being redirected hell knows where.
                //Skip
                return false;
            }
            //TODO OutOfMemory thrown here
            reader = new SamlibAuthorPageReader(request.body());
            //We go a blank response but no exception, skip author
            if (reader.isPageBlank()) {
                return false;
            }
        } catch (MalformedURLException e) {
            //Just swallow exception, as this is unlikely to happen
            //Skip author
            trackException(e.getMessage());
            return false;
        } catch (HttpRequest.HttpRequestException e) {
            //Author currently inaccessible or no internet
            //Skip author
            trackException(e.getMessage());
            return false;
        }
        AuthorDao authorDao = null;
        PublicationDao publicationsDao = null;

        try {
            publicationsDao = helper.getDao(Publication.class);
        } catch (SQLException e) {
            Log.e("Samlib", "Could not create DAO publicationsDao", e);
        }
        try {
            authorDao = helper.getDao(Author.class);
        } catch (SQLException e) {
            Log.e("Samlib", "Could not create DAO authorDao", e);
        }

        assert authorDao != null;
        assert publicationsDao != null;

        String authImgUrl = reader.getAuthorImageUrl(author.getUrl());
        String authDescription = reader.getAuthorDescription();
        if (authImgUrl != null) {
            author.setAuthorImageUrl(authImgUrl);
        }
        if (authDescription != null) {
            author.setAuthorDescription(authDescription);
        }

        authorDao.update(author);

        ForeignCollection<Publication> oldItems = author.getPublications();
        List<Publication> newItems = reader.getPublications(author);

        HashMap<String, Publication> oldItemsMap = new HashMap<String, Publication>();
        for (Publication oldPub : oldItems) {
            oldItemsMap.put(oldPub.getUrl(), oldPub);
        }

        if (newItems.size() == 0 && oldItemsMap.size() > 1) {
            LogUtils.LOGW(Constants.APP_TAG,
                    "Something went wrong. No publications found for author that already exists");
            //Just skip for now to be on the safe side.
            return false;
        }

        for (Publication pub : newItems) {
            //Find pub in oldItems
            if (oldItemsMap.containsKey(pub.getUrl())) {
                Publication old = oldItemsMap.get(pub.getUrl());
                if (old.getUpdatesIgnored()) {
                    //Do not check anything
                    continue;
                }
                //Check size/name/description
                if (pub.getSize() != old.getSize() || !pub.getName().equals(old.getName())) {
                    //if something differs
                    //Store the old size
                    if (old.getOldSize() != 0) {
                        pub.setOldSize(old.getOldSize());
                    } else {
                        pub.setOldSize(old.getSize());
                    }
                    //Swap the ids, do an update in DB
                    pub.setId(old.getId());
                    //Copy over custom properties that do not relate to samlib
                    pub.setMyVote(old.getMyVote());
                    pub.setVoteCookie(old.getVoteCookie());
                    pub.setVoteDate(old.getVoteDate());
                    pub.setUpdatesIgnored(old.getUpdatesIgnored());
                    pub.setNew(true);
                    authorUpdated = true;
                    publicationsDao.update(pub);
                    //Mark author new, update in DB
                    author.setUpdateDate(new Date());
                    author.setNew(true);
                    authorDao.update(author);
                } else if (!StringUtils.equalsIgnoreCase(old.getImagePageUrl(), pub.getImagePageUrl())) {
                    pub.setId(old.getId());
                    //Update silently
                    publicationsDao.update(pub);
                }
            } else {
                //Mark author new, update in DB
                author.setUpdateDate(new Date());
                author.setNew(true);
                authorDao.update(author);
                //Mark publication new, create in DB
                pub.setNew(true);
                authorUpdated = true;
                publicationsDao.create(pub);
            }
        }

        return authorUpdated;
    }

    private void trackException(String message) {
        AnalyticsHelper.getInstance().sendException(message);
    }
}