com.acrutiapps.browser.tasks.HistoryBookmarksImportTask.java Source code

Java tutorial

Introduction

Here is the source code for com.acrutiapps.browser.tasks.HistoryBookmarksImportTask.java

Source

/*
 * Tint Browser for Android
 * 
 * Copyright (C) 2012 - to infinity and beyond J. Devauchelle and contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 3 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

package com.acrutiapps.browser.tasks;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.acrutiapps.browser.R;
import com.acrutiapps.browser.providers.BookmarksProvider;
import com.acrutiapps.browser.ui.preferences.IHistoryBookmaksImportListener;

import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;

public class HistoryBookmarksImportTask extends AsyncTask<String, Integer, String> {

    private Context mContext;
    private IHistoryBookmaksImportListener mListener;

    public HistoryBookmarksImportTask(Context context, IHistoryBookmaksImportListener listener) {
        mContext = context;
        mListener = listener;
    }

    @Override
    protected String doInBackground(String... params) {

        publishProgress(0, 0, 0);

        File file = new File(Environment.getExternalStorageDirectory(), params[0]);

        if ((file != null) && (file.exists()) && (file.canRead())) {

            if (file.getName().toLowerCase(Locale.US).endsWith(".json")) {
                return readAsJSON(file);
            } else if (file.getName().toLowerCase(Locale.US).endsWith(".xml")) {
                return readAsXml(file);
            } else {
                return mContext.getString(R.string.HistoryBookmarksImportErrorInvalidFileFormat);
            }

        } else {
            return mContext.getString(R.string.HistoryBookmarksImportFileUnavailable);
        }
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        mListener.onImportProgress(values[0], values[1], values[2]);
    }

    @Override
    protected void onPostExecute(String result) {
        mListener.onImportDone(result);
    }

    private String readAsJSON(File file) {
        List<ContentValues> insertValues = null;

        try {
            insertValues = new ArrayList<ContentValues>();

            publishProgress(1, 0, 0);

            FileInputStream fis = new FileInputStream(file);

            StringBuilder sb = new StringBuilder();
            String line;

            BufferedReader reader;
            try {
                reader = new BufferedReader(new InputStreamReader(fis, "UTF-8"));

                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return e.getMessage();
            } catch (IOException e) {
                e.printStackTrace();
                return e.getMessage();
            } finally {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    return e.getMessage();
                }
            }

            JSONObject data = new JSONObject(sb.toString());

            Map<Long, Folder> folders = new HashMap<Long, Folder>();

            if (data.has("folders")) {
                JSONArray foldersArray = data.getJSONArray("folders");

                int progress = 0;
                int total = foldersArray.length();

                for (int i = 0; i < foldersArray.length(); i++) {

                    publishProgress(3, progress, total);

                    JSONObject folder = foldersArray.getJSONObject(i);

                    long id = folder.getLong("id");
                    long parentId = folder.getLong("parentId");
                    String title = URLDecoder.decode(folder.getString("title"), "UTF-8");

                    ContentValues values = new ContentValues();
                    values.put(BookmarksProvider.Columns.TITLE, title);
                    values.put(BookmarksProvider.Columns.BOOKMARK, 0);
                    values.put(BookmarksProvider.Columns.IS_FOLDER, 1);
                    values.put(BookmarksProvider.Columns.PARENT_FOLDER_ID, -1);

                    Uri insertionUri = mContext.getContentResolver().insert(BookmarksProvider.BOOKMARKS_URI,
                            values);
                    String insertionString = insertionUri.toString();

                    // Get the new id for the current folder.
                    long insertionId = -1;
                    try {
                        insertionId = Long
                                .parseLong(insertionString.substring(insertionString.lastIndexOf('/') + 1));
                    } catch (NumberFormatException e) {
                        insertionId = -1;
                    }

                    // Keep a relation between the id of the folder in the export file, its parent id (in the export file), and its new id.
                    folders.put(id, new Folder(insertionId, parentId));

                    progress++;
                }

                publishProgress(4, 0, 0);

                // Correct folders parent ids.
                if (!folders.isEmpty()) {
                    for (Folder folder : folders.values()) {
                        // For each folder previously inserted, check if it had a parent folder in the export file.
                        long oldParentId = folder.getOldParentId();

                        if (oldParentId != -1) {
                            // Get the parent folder by its old Id, key of folders map.
                            Folder parentFolder = folders.get(oldParentId);
                            if (parentFolder != null) {

                                ContentValues values = new ContentValues();
                                values.put(BookmarksProvider.Columns.PARENT_FOLDER_ID, parentFolder.getNewId());

                                String whereClause = BookmarksProvider.Columns._ID + " = " + folder.getNewId();

                                mContext.getContentResolver().update(BookmarksProvider.BOOKMARKS_URI, values,
                                        whereClause, null);
                            }
                        }
                    }
                }
            }

            if (data.has("bookmarks")) {
                JSONArray bookmarksArray = data.getJSONArray("bookmarks");

                int progress = 0;
                int total = bookmarksArray.length();

                for (int i = 0; i < bookmarksArray.length(); i++) {

                    publishProgress(5, progress, total);

                    JSONObject bookmark = bookmarksArray.getJSONObject(i);

                    long folderId = bookmark.getLong("folderId");
                    Folder parentFolder = null;
                    if (folderId != -1) {
                        parentFolder = folders.get(folderId);
                    }

                    String title = URLDecoder.decode(bookmark.getString("title"), "UTF-8");
                    String url = URLDecoder.decode(bookmark.getString("url"), "UTF-8");

                    ContentValues values = createContentValues(title, url, bookmark.getInt("visits"),
                            bookmark.getLong("visitedDate"), bookmark.getLong("creationDate"), 1);

                    if (parentFolder != null) {
                        values.put(BookmarksProvider.Columns.PARENT_FOLDER_ID, parentFolder.getNewId());
                    }

                    insertValues.add(values);

                    progress++;
                }
            }

            if (data.has("history")) {
                JSONArray historyArray = data.getJSONArray("history");

                int progress = 0;
                int total = historyArray.length();

                for (int i = 0; i < historyArray.length(); i++) {

                    publishProgress(6, progress, total);

                    JSONObject history = historyArray.getJSONObject(i);

                    String title = URLDecoder.decode(history.getString("title"), "UTF-8");
                    String url = URLDecoder.decode(history.getString("url"), "UTF-8");

                    ContentValues values = createContentValues(title, url, history.getInt("visits"),
                            history.getLong("visitedDate"), 0, 0);

                    insertValues.add(values);

                    progress++;
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return e.getMessage();
        } catch (JSONException e) {
            e.printStackTrace();
            return e.getMessage();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return e.getMessage();
        }

        if (insertValues != null) {
            publishProgress(7, 0, 0);
            mContext.getContentResolver().bulkInsert(BookmarksProvider.BOOKMARKS_URI,
                    insertValues.toArray(new ContentValues[insertValues.size()]));
        }

        return null;
    }

    private String readAsXml(File file) {
        List<ContentValues> values = null;

        try {

            publishProgress(1, 0, 0);

            values = new ArrayList<ContentValues>();

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder;

            builder = factory.newDocumentBuilder();
            Document document = builder.parse(file);

            Element root = document.getDocumentElement();

            if ((root != null) && (root.getNodeName().equals("itemlist"))) {

                NodeList itemsList = root.getElementsByTagName("item");

                int progress = 0;
                int total = itemsList.getLength();

                Node item;
                NodeList record;
                Node dataItem;

                for (int i = 0; i < itemsList.getLength(); i++) {

                    publishProgress(2, progress, total);

                    item = itemsList.item(i);

                    if (item != null) {
                        record = item.getChildNodes();

                        String title = null;
                        String url = null;
                        int visits = 0;
                        long visitedDate = -1;
                        long creationDate = -1;
                        int bookmark = 0;

                        for (int j = 0; j < record.getLength(); j++) {
                            dataItem = record.item(j);

                            if ((dataItem != null) && (dataItem.getNodeName() != null)) {

                                if (dataItem.getNodeName().equals("title")) {
                                    title = URLDecoder.decode(getNodeContent(dataItem), "UTF-8");
                                } else if (dataItem.getNodeName().equals("url")) {
                                    url = URLDecoder.decode(getNodeContent(dataItem), "UTF-8");
                                } else if (dataItem.getNodeName().equals("visits")) {
                                    try {
                                        visits = Integer.parseInt(getNodeContent(dataItem));
                                    } catch (Exception e) {
                                        visits = 0;
                                    }
                                } else if (dataItem.getNodeName().equals("visiteddate")) {
                                    try {
                                        visitedDate = Long.parseLong(getNodeContent(dataItem));
                                    } catch (Exception e) {
                                        visitedDate = -1;
                                    }
                                } else if (dataItem.getNodeName().equals("creationdate")) {
                                    try {
                                        creationDate = Long.parseLong(getNodeContent(dataItem));
                                    } catch (Exception e) {
                                        creationDate = -1;
                                    }
                                } else if (dataItem.getNodeName().equals("bookmark")) {
                                    try {
                                        bookmark = Integer.parseInt(getNodeContent(dataItem));
                                    } catch (Exception e) {
                                        bookmark = 0;
                                    }
                                }
                            }
                        }

                        values.add(createContentValues(title, url, visits, visitedDate, creationDate, bookmark));
                    }

                    progress++;
                }
            }

        } catch (ParserConfigurationException e) {
            return e.getMessage();
        } catch (SAXException e) {
            return e.getMessage();
        } catch (IOException e) {
            return e.getMessage();
        }

        if (values != null) {
            publishProgress(7, 0, 0);
            mContext.getContentResolver().bulkInsert(BookmarksProvider.BOOKMARKS_URI,
                    values.toArray(new ContentValues[values.size()]));
        }

        return null;
    }

    /**
     * Get the content of a node, why Android does not include Node.getTextContent() ?
     * @param node The node.
     * @return The node content.
     */
    private String getNodeContent(Node node) {
        StringBuffer buffer = new StringBuffer();
        NodeList childList = node.getChildNodes();
        for (int i = 0; i < childList.getLength(); i++) {
            Node child = childList.item(i);
            if (child.getNodeType() != Node.TEXT_NODE) {
                continue; // skip non-text nodes
            }
            buffer.append(child.getNodeValue());
        }

        return buffer.toString();
    }

    private ContentValues createContentValues(String title, String url, int visits, long visitedDate,
            long creationDate, int bookmark) {
        ContentValues values = new ContentValues();
        values.put(BookmarksProvider.Columns.TITLE, title);
        values.put(BookmarksProvider.Columns.URL, url);
        values.put(BookmarksProvider.Columns.VISITS, visits);

        if (visitedDate > 0) {
            values.put(BookmarksProvider.Columns.VISITED_DATE, visitedDate);
        } else {
            values.putNull(BookmarksProvider.Columns.VISITED_DATE);
        }

        if (creationDate > 0) {
            values.put(BookmarksProvider.Columns.CREATION_DATE, creationDate);
        } else {
            values.putNull(BookmarksProvider.Columns.CREATION_DATE);
        }

        if (bookmark > 0) {
            values.put(BookmarksProvider.Columns.BOOKMARK, 1);
        } else {
            values.put(BookmarksProvider.Columns.BOOKMARK, 0);
        }

        return values;
    }

    /**
     * Store the new id of a folder, and its
     * old parent id. E.g. the parent id in the export file.
     */
    private class Folder {
        private long mNewId;
        private long mOldParentId;

        public Folder(long newId, long oldParentId) {
            mNewId = newId;
            mOldParentId = oldParentId;
        }

        public long getNewId() {
            return mNewId;
        }

        public long getOldParentId() {
            return mOldParentId;
        }
    }

}