eu.nerdz.api.impl.fastreverse.messages.FastReverseConversationHandler.java Source code

Java tutorial

Introduction

Here is the source code for eu.nerdz.api.impl.fastreverse.messages.FastReverseConversationHandler.java

Source

/*
 * This file is part of NerdzApi-java.
 *
 *     NerdzApi-java is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     NerdzApi-java 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.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with NerdzApi-java.  If not, see <http://www.gnu.org/licenses/>.
 *
 *     (C) 2013 Marco Cilloni <marco.cilloni@yahoo.com>
 */

package eu.nerdz.api.impl.fastreverse.messages;

/*
 This file is part of NerdzApi-java.
    
NerdzApi-java is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
NerdzApi-java 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.
    
You should have received a copy of the GNU General Public License
along with NerdzApi-java.  If not, see <http://www.gnu.org/licenses/>.
    
(C) 2013 Marco Cilloni <marco.cilloni@yahoo.com>
*/

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import eu.nerdz.api.ContentException;
import eu.nerdz.api.HttpException;
import eu.nerdz.api.UserInfo;
import eu.nerdz.api.impl.reverse.messages.ReverseConversationHandler;
import eu.nerdz.api.impl.reverse.messages.ReverseMessenger;
import eu.nerdz.api.messages.Conversation;
import eu.nerdz.api.messages.Message;

public class FastReverseConversationHandler extends ReverseConversationHandler {

    private final UserInfo mUserInfo;

    public FastReverseConversationHandler(ReverseMessenger messenger) {
        super(messenger);
        this.mUserInfo = messenger.getUserInfo();
    }

    @Override
    public List<Conversation> getConversations() throws IOException, HttpException, ContentException {

        String response = this.mMessenger.get("/fastfetch.json.php?action=conversations");

        try {

            JSONObject errorObj = new JSONObject(response); //if this raises an exception, it's not an error response
            throw new ContentException(FastReverseErrCode.fromCode(errorObj.getInt("error")).toString());

        } catch (JSONException e) {

            try {

                JSONArray jsonResponse;

                jsonResponse = new JSONArray(response);

                int length = jsonResponse.length();

                List<Conversation> conversations = new ArrayList<Conversation>(length);

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

                    JSONObject conversation = jsonResponse.getJSONObject(i);

                    conversations.add(new FastReverseConversation(

                            conversation.getString("name"), conversation.getInt("id"),
                            new Date(conversation.getLong("last_timestamp") * 1000L),
                            FastReverseConversationHandler.replaceBbcode(conversation.getString("last_message")),
                            conversation.getInt("last_sender") != this.mMessenger.getUserID(),
                            conversation.getBoolean("new_messages")

                    ));
                }

                return conversations;
            } catch (JSONException e1) {

                throw new ContentException("Invalid json response from FastFetch");

            }
        }

    }

    /**
     * This is the only method that needs of being overloaded, because it does all message fetching.
     * {@inheritDoc}
     */
    @Override
    protected Pair<List<Message>, Boolean> getMessagesAndCheck(Conversation conversation, int start, int howMany)
            throws IOException, HttpException, ContentException {

        if (howMany > 30) {
            howMany = 30;
        }

        if (start == 0 && howMany == 1 && conversation instanceof FastReverseConversation) { //FastReverseConversations contain the content of the last message - so we take this fast path.

            Pair<String, Boolean> lastInfo = ((FastReverseConversation) conversation).getLastMessageInfo();

            List<Message> lastMessage = new ArrayList<Message>(1);
            lastMessage.add(new FastReverseMessage(conversation, this.mUserInfo, conversation.getLastDate(),
                    lastInfo.getLeft(), lastInfo.getRight(), false));

            return new ImmutablePair<List<Message>, Boolean>(lastMessage, false);
        }

        String response = this.mMessenger.get("/fastfetch.json.php?action=messages&otherid="
                + conversation.getOtherID() + "&start=" + start + "&limit=" + (howMany + 1));

        try {

            JSONObject errorObj = new JSONObject(response); //if this raises an exception, it's not an error response
            throw new ContentException(FastReverseErrCode.fromCode(errorObj.getInt("error")).toString());

        } catch (JSONException e) {

            try {

                JSONArray jsonResponse = new JSONArray(response);

                int length = jsonResponse.length();

                boolean hasMore = length > howMany; //if howMany is n, previously i've tried to fetch n + 1; if the number of elements fetched is really n + 1 this means that there are more messages.

                length = hasMore ? howMany : length;

                LinkedList<Message> conversationList = new LinkedList<Message>();

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

                    JSONObject conversationJson = jsonResponse.getJSONObject(i);

                    boolean received = !conversationJson.getBoolean("sent");

                    conversationList.addFirst(new FastReverseMessage(conversation, this.mUserInfo,
                            new Date(conversationJson.getLong("timestamp") * 1000L),
                            FastReverseConversationHandler.replaceBbcode(conversationJson.getString("message")),
                            received, conversationJson.getBoolean("read")));
                }

                return new ImmutablePair<List<Message>, Boolean>(conversationList, hasMore);
            } catch (JSONException e1) {

                e1.printStackTrace();

                throw new ContentException("Invalid json response from FastFetch");

            }
        }

    }

    /**
     * Replaces BBCode tags with URLs, removing all the rest.
     * @param message A message String
     * @return A parsed String
     */
    private static String replaceBbcode(String message) {
        message = message.replaceAll("(?i)\\[hr\\]", "\n");
        message = FastReverseConversationHandler.replaceYoutubeVideos(message);
        //message = FastReverseConversationHandler.replaceImages(message);
        //message = FastReverseConversationHandler.replaceUrls(message);
        message = FastReverseConversationHandler.replaceCode(message);
        return message;
    }

    /**
     * Replaces a single tag.
     * @param regex A regex
     * @param message A message to be parsed
     * @return A string in which all occurrences of regex have been substituted with the contents matched
     */
    private static String replaceSingle(String regex, String message) {

        Matcher matcher = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE).matcher(message);
        StringBuffer result = new StringBuffer();

        while (matcher.find()) {
            matcher.appendReplacement(result, matcher.group(1).replace("$", "\\$"));
        }

        matcher.appendTail(result);

        return result.toString();
    }

    /**
     * Replaces a composite tag.
     * @param regex A regex
     * @param message A message to be parsed
     * @param format A format for pretty formatting. Only 2 string fields.
     * @return A string in which all occurrences of regex have been substituted with the contents matched
     */
    private static String replaceDouble(String regex, String message, String format) {

        Matcher matcher = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE).matcher(message);
        StringBuffer result = new StringBuffer();

        while (matcher.find()) {
            matcher.appendReplacement(result,
                    String.format(format, matcher.group(1), matcher.group(2)).replace("$", "\\$"));
        }

        matcher.appendTail(result);

        return result.toString();

    }

    /**
     * Parses images tags.
     * @param message A message to be parsed
     * @return A string in which all [img]s have been replaced with their URLs
     */
    private static String replaceImages(String message) {
        return FastReverseConversationHandler.replaceSingle("\\[img\\](.*?)\\[/img\\]", message);
    }

    /**
     * Parses YouTube tags.
     * @param message A message to be parsed
     * @return A string in which all [yt]s and [youtube]s have been replaced with their URLs
     */
    private static String replaceYoutubeVideos(String message) {
        return FastReverseConversationHandler.replaceSingle("\\[yt\\](.*?)\\[/yt\\]",
                FastReverseConversationHandler.replaceSingle("\\[youtube\\](.*?)\\[/youtube\\]", message));
    }

    /**
     * Parses URLs.
     * @param message A message to be parsed
     * @return A string in which all [url]s and [url=...]s have been replaced with their URLs (and description)
     */
    private static String replaceUrls(String message) {

        return FastReverseConversationHandler.replaceSingle("\\[url\\](.*?)\\[/url\\]",
                FastReverseConversationHandler.replaceDouble("\\[url=(.*?)\\](.*?)\\[/url\\]", message,
                        "%2$s (%1$s)")); //replace banal urls as anything else

    }

    private static String replaceCode(String message) {
        return FastReverseConversationHandler.replaceDouble("\\[code=(.*?)\\](.*?)\\[/code\\]", message,
                "\n[b]```%1$s[/b]\n%2$s\n[b]```[/b]\n");
    }

}