com.magnet.mmx.server.plugin.mmxmgmt.handler.MessageStateHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.magnet.mmx.server.plugin.mmxmgmt.handler.MessageStateHandler.java

Source

/*   Copyright (c) 2015 Magnet Systems, Inc.
 *
 *  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.magnet.mmx.server.plugin.mmxmgmt.handler;

import com.magnet.mmx.protocol.Constants;
import com.magnet.mmx.protocol.MsgId;
import com.magnet.mmx.protocol.MsgEvents;
import com.magnet.mmx.protocol.MsgTags;
import com.magnet.mmx.protocol.MsgsState;
import com.magnet.mmx.protocol.MsgsState.MessageStatusList;
import com.magnet.mmx.protocol.StatusCode;
import com.magnet.mmx.server.plugin.mmxmgmt.db.MessageDAO;
import com.magnet.mmx.server.plugin.mmxmgmt.db.MessageDAOImpl;
import com.magnet.mmx.server.plugin.mmxmgmt.db.MessageEntity;
import com.magnet.mmx.server.plugin.mmxmgmt.db.OpenFireDBConnectionProvider;
import com.magnet.mmx.server.plugin.mmxmgmt.db.SearchResult;
import com.magnet.mmx.server.plugin.mmxmgmt.util.IQUtils;
import com.magnet.mmx.server.plugin.mmxmgmt.util.JIDUtil;
import com.magnet.mmx.server.plugin.mmxmgmt.web.MessageSearchOption;
import com.magnet.mmx.server.plugin.mmxmgmt.web.MessageSortOption;
import com.magnet.mmx.server.plugin.mmxmgmt.search.PaginationInfo;
import com.magnet.mmx.server.plugin.mmxmgmt.web.ValueHolder;
import com.magnet.mmx.util.GsonData;

import org.dom4j.Element;
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.handler.IQHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Handler for message states and tags.
 */
public class MessageStateHandler extends IQHandler {
    private static Logger LOGGER = LoggerFactory.getLogger(MessageStateHandler.class);
    private static final MsgsState.MessageStatus UNKNOWN_MSG_STATUS = new MsgsState.MessageStatus()
            .setState(Constants.MessageState.UNKNOWN);

    /**
     * Constructor that takes the module name
     *
     * @param moduleName
     */
    public MessageStateHandler(String moduleName) {
        super(moduleName);
    }

    @Override
    public IQ handleIQ(IQ iq) throws UnauthorizedException {
        JID fromJID = iq.getFrom();
        String appId = JIDUtil.getAppId(fromJID);
        //read the command
        Element element = iq.getChildElement();
        String payload = element.getText();
        String commandId = element.attributeValue(Constants.MMX_ATTR_COMMAND);

        if (commandId == null || commandId.isEmpty() || commandId.trim().isEmpty()) {
            return IQUtils.createErrorIQ(iq, MessageStatusCode.INVALID_COMMAND.getMessage(),
                    MessageStatusCode.INVALID_COMMAND.getCode());
        }

        Constants.MessageCommand command = null;
        try {
            command = Constants.MessageCommand.valueOf(commandId);
        } catch (IllegalArgumentException e) {
            LOGGER.info("Invalid device command string:" + commandId, e);
        }
        if (command == null) {
            return IQUtils.createErrorIQ(iq, MessageStatusCode.INVALID_COMMAND.getMessage(),
                    MessageStatusCode.INVALID_COMMAND.getCode());
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Processing command:" + command.toString());
        }

        switch (command) {
        case query:
            return processMessageQuery(iq, appId, payload);
        case getTags:
            return processGetTags(iq, appId, payload);
        case setTags:
            return processSetTags(iq, appId, payload);
        case addTags:
            return processAddTags(iq, appId, payload);
        case removeTags:
            return processRemoveTags(iq, appId, payload);
        case getEvents:
            return processGetEvents(iq, appId, payload);
        case setEvents:
            return processSetEvents(iq, appId, payload);
        case addEvents:
            return processAddEvents(iq, appId, payload);
        case removeEvents:
            return processRemoveEvents(iq, appId, payload);
        default:
            LOGGER.info("Unknown message command");
            return IQUtils.createErrorIQ(iq, MessageStatusCode.INVALID_COMMAND.getMessage(),
                    MessageStatusCode.INVALID_COMMAND.getCode());
        }
    }

    @Override
    public IQHandlerInfo getInfo() {
        return new IQHandlerInfo(Constants.MMX, Constants.MMX_NS_MSG_STATE);
    }

    /**
     * Validate the incoming packet
     *
     * @param iq
     */
    private void validate(IQ iq) {
        //TODO: add validation rules
    }

    private IQ processMessageQuery(IQ source, String appId, String payload) {
        MsgsState.Request requestList = MsgsState.Request.fromJson(payload);
        if (requestList.size() == 0) {
            //no ids here
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID_LIST.getMessage(),
                    MessageStatusCode.INVALID_MSG_ID_LIST.getCode());
        }
        MsgsState.Response response = new MsgsState.Response();
        MessageDAO dao = getMessageDAO();
        // TODO: it would be more efficient if the DAO can get messages with a list
        // of message ID's.
        for (String messageId : requestList) {
            List<MessageEntity> messageList = dao.getMessages(appId, messageId);
            if (messageList.size() == 0) {
                // For non-existing message ID, return UNKNOWN state.
                MessageStatusList list = new MessageStatusList(1);
                list.add(UNKNOWN_MSG_STATUS);
                response.put(messageId, list);
                continue;
            }
            HashMap<String, HashMap<String, MessageEntity.MessageState>> result = new HashMap<String, HashMap<String, MessageEntity.MessageState>>();
            for (MessageEntity me : messageList) {
                HashMap<String, MessageEntity.MessageState> userMsg = result.get(messageId);
                if (userMsg == null) {
                    userMsg = new HashMap<String, MessageEntity.MessageState>();
                    result.put(messageId, userMsg);
                }
                String userId = JIDUtil.getUserId(me.getTo());
                MessageEntity.MessageState state = userMsg.get(userId);
                if (state == null) {
                    state = me.getState();
                    userMsg.put(userId, state);
                } else {
                    if (state.getPriority() < me.getState().getPriority()) {
                        // Do the state aggregation; use the priority of a state.
                        // If multiple states having same priority is supported, it should 
                        // consider device priority and the modified time.
                        userMsg.put(userId, me.getState());
                    }
                }
            }

            // Convert the aggregated result to the final response.
            // TODO: consolidate the MessageEntity.MessageState with Constants.MessageState
            for (Map.Entry<String, HashMap<String, MessageEntity.MessageState>> entry : result.entrySet()) {
                MessageStatusList list = new MessageStatusList(entry.getValue().size());
                for (Map.Entry<String, MessageEntity.MessageState> stateEntry : entry.getValue().entrySet()) {
                    list.add(new MsgsState.MessageStatus().setRecipient(stateEntry.getKey())
                            .setState(Constants.MessageState.valueOf(stateEntry.getValue().toString())));
                }
                response.put(entry.getKey(), list);
            }
        }

        return IQUtils.createResultIQ(source, response.toJson());
    }

    private IQ processGetTags(IQ source, String appId, String payload) {
        MsgId rqt = GsonData.getGson().fromJson(payload, MsgId.class);
        if (rqt == null || rqt.getMsgId() == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + "null",
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();

        // TODO: verify the msg ID (normal or push message) and get the tags.
        List<String> tags = new ArrayList<String>();
        MsgTags response = new MsgTags(rqt.getIdType(), rqt.getMsgId(), tags, new Date());

        return IQUtils.createResultIQ(source, response.toJson());
    }

    private IQ processSetTags(IQ source, String appId, String payload) {
        MsgTags msgTags = MsgTags.fromJson(payload);
        MsgId.IdType idType = msgTags.getIdType();
        String msgId = msgTags.getMsgId();
        if (msgId == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + msgId,
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();
        // TODO: verify the msg ID (normal or push message) and set the tags.

        return IQUtils.createErrorIQ(source, "Update tags is not implemented", StatusCode.NOT_IMPLEMENTED);

        //    MMXStatus status = new MMXStatus()
        //        .setCode(MessageStatusCode.SUCCESS.getCode())
        //        .setMessage(MessageStatusCode.SUCCESS.getMessage());
        //    return IQUtils.createResultIQ(source, status.toJson());
    }

    private IQ processAddTags(IQ source, String appId, String payload) {
        MsgTags msgTags = MsgTags.fromJson(payload);
        MsgId.IdType idType = msgTags.getIdType();
        String msgId = msgTags.getMsgId();
        if (msgId == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + msgId,
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();
        // TODO: verify the msg ID (normal or push message) and add the tags.

        return IQUtils.createErrorIQ(source, "Adding tags is not implemented", StatusCode.NOT_IMPLEMENTED);

        //    MMXStatus status = new MMXStatus()
        //        .setCode(MessageStatusCode.SUCCESS.getCode())
        //        .setMessage(MessageStatusCode.SUCCESS.getMessage());
        //    return IQUtils.createResultIQ(source, status.toJson());
    }

    private IQ processRemoveTags(IQ source, String appId, String payload) {
        MsgTags msgTags = MsgTags.fromJson(payload);
        MsgId.IdType idType = msgTags.getIdType();
        String msgId = msgTags.getMsgId();
        if (msgId == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + msgId,
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();
        // TODO: verify the msg ID (normal or push message) and remove the tags.

        return IQUtils.createErrorIQ(source, "Tags removal is not implemented", StatusCode.NOT_IMPLEMENTED);

        //    MMXStatus status = new MMXStatus()
        //        .setCode(MessageStatusCode.SUCCESS.getCode())
        //        .setMessage(MessageStatusCode.SUCCESS.getMessage());
        //    return IQUtils.createResultIQ(source, status.toJson());
    }

    private IQ processGetEvents(IQ source, String appId, String payload) {
        MsgId rqt = GsonData.getGson().fromJson(payload, MsgId.class);
        if (rqt == null || rqt.getMsgId() == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + "null",
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();

        // TODO: verify the msg ID (normal or push message) and get the events.
        List<String> tags = new ArrayList<String>();
        MsgEvents response = new MsgEvents(rqt.getIdType(), rqt.getMsgId(), tags, new Date());

        return IQUtils.createResultIQ(source, response.toJson());
    }

    private IQ processSetEvents(IQ source, String appId, String payload) {
        MsgEvents msgEvents = MsgEvents.fromJson(payload);
        MsgId.IdType idType = msgEvents.getIdType();
        String msgId = msgEvents.getMsgId();
        if (msgId == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + msgId,
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();
        // TODO: verify the msg ID (normal or push message) and set the events.

        return IQUtils.createErrorIQ(source, "Update tags is not implemented", StatusCode.NOT_IMPLEMENTED);

        //    MMXStatus status = new MMXStatus()
        //        .setCode(MessageStatusCode.SUCCESS.getCode())
        //        .setMessage(MessageStatusCode.SUCCESS.getMessage());
        //    return IQUtils.createResultIQ(source, status.toJson());
    }

    private IQ processAddEvents(IQ source, String appId, String payload) {
        MsgEvents msgEvents = MsgEvents.fromJson(payload);
        MsgId.IdType idType = msgEvents.getIdType();
        String msgId = msgEvents.getMsgId();
        if (msgId == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + msgId,
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();
        // TODO: verify the msg ID (normal or push message) and add the events.

        return IQUtils.createErrorIQ(source, "Adding tags is not implemented", StatusCode.NOT_IMPLEMENTED);

        //    MMXStatus status = new MMXStatus()
        //        .setCode(MessageStatusCode.SUCCESS.getCode())
        //        .setMessage(MessageStatusCode.SUCCESS.getMessage());
        //    return IQUtils.createResultIQ(source, status.toJson());
    }

    private IQ processRemoveEvents(IQ source, String appId, String payload) {
        MsgEvents msgEvents = MsgEvents.fromJson(payload);
        MsgId.IdType idType = msgEvents.getIdType();
        String msgId = msgEvents.getMsgId();
        if (msgId == null) {
            return IQUtils.createErrorIQ(source, MessageStatusCode.INVALID_MSG_ID.getMessage() + msgId,
                    MessageStatusCode.INVALID_MSG_ID.getCode());
        }
        MessageDAO dao = getMessageDAO();
        // TODO: verify the msg ID (normal or push message) and remove the events.

        return IQUtils.createErrorIQ(source, "Tags removal is not implemented", StatusCode.NOT_IMPLEMENTED);

        //    MMXStatus status = new MMXStatus()
        //        .setCode(MessageStatusCode.SUCCESS.getCode())
        //        .setMessage(MessageStatusCode.SUCCESS.getMessage());
        //    return IQUtils.createResultIQ(source, status.toJson());
    }

    public MessageDAO getMessageDAO() {
        MessageDAO dao = new MessageDAOImpl(new OpenFireDBConnectionProvider());
        return dao;
    }

    /**
     * Enum for the status codes
     */
    public static enum MessageStatusCode {
        SUCCESS(200, "SUCCESS"), INVALID_COMMAND(400, "Invalid command"), INVALID_MSG_ID(400,
                "Invalid message id: "), INVALID_MSG_ID_LIST(400, "Invalid message id list"),;

        private int code;
        private String message;

        MessageStatusCode(int c, String m) {
            code = c;
            message = m;
        }

        public int getCode() {
            return code;
        }

        public String getMessage() {
            return message;
        }
    }
}