ch.windmobile.server.social.mongodb.ChatServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for ch.windmobile.server.social.mongodb.ChatServiceImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2011 epyx SA.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * 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 Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package ch.windmobile.server.social.mongodb;

import java.util.ArrayList;
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;

import ch.windmobile.server.socialmodel.ChatService;
import ch.windmobile.server.socialmodel.xml.Message;
import ch.windmobile.server.socialmodel.xml.Messages;

import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

public class ChatServiceImpl extends BaseMongoDBService implements ChatService {
    private static final String counter = "function counter(name) { return db."
            + MongoDBConstants.COLLECTION_CHATROOMS
            + ".findAndModify({query:{_id:name}, update:{$inc : {counter:1}}, new:true, upsert:true}).counter; }";

    public ChatServiceImpl(DB database) {
        super(database);
    }

    private String computeCollectionName(final String chatRoomId) {
        return MongoDBConstants.COLLECTION_CHAT_ROOM_PREFIX + chatRoomId;
    }

    private DBCollection createChatCappedCollection(String collectionName) {
        DBObject options = BasicDBObjectBuilder.start("capped", true).add("size", 10000).get();
        // create the capped chat room of 10K
        return db.createCollection(collectionName, options);
    }

    public DBCollection getOrCreateCappedCollection(String collectionName) {
        DBCollection col;
        try {
            // try to create the collection, it may raise an exception if already create, in this case just ignore it
            // and get the collection
            // Due to the "consistency" behavior of mongoDB trying to first check if the collection exist the create it
            // will not work, race condition will certainly occurs...
            col = createChatCappedCollection(collectionName);
        } catch (Exception ex) {
            col = db.getCollection(collectionName);
        }
        return col;
    }

    @Override
    public Message postMessage(String chatRoomId, String pseudo, String text, String emailHash) {
        String collectionName = computeCollectionName(chatRoomId);
        DBCollection col = getOrCreateCappedCollection(collectionName);

        DBObject chatItem = new BasicDBObject();
        Double id = (Double) db.eval(counter, chatRoomId);
        chatItem.put("_id", id.longValue());
        chatItem.put(MongoDBConstants.CHAT_PROP_TEXT, text);
        chatItem.put(MongoDBConstants.CHAT_PROP_USER, pseudo);
        DateTime date = new DateTime().toDateTimeISO();
        chatItem.put(MongoDBConstants.CHAT_PROP_TIME, date.toString());
        chatItem.put(MongoDBConstants.CHAT_PROP_EMAIL_HASH, emailHash);
        col.insert(chatItem);

        Message message = new Message();
        message.setId(id.toString());
        message.setDate(date);
        message.setPseudo(pseudo);
        message.setText(text);
        message.setEmailHash(emailHash);

        return message;
    }

    @Override
    public Messages findMessages(String chatRoomId, int maxCount) {
        if (maxCount <= 0) {
            throw new IllegalArgumentException("maxCount arg[1] must be greater than 0");
        }
        final String collectionName = computeCollectionName(chatRoomId);

        final DBObject fields = BasicDBObjectBuilder.start("_id", 1).add(MongoDBConstants.CHAT_PROP_USER, 1)
                .add(MongoDBConstants.CHAT_PROP_TEXT, 1).add(MongoDBConstants.CHAT_PROP_TIME, 1)
                .add(MongoDBConstants.CHAT_PROP_EMAIL_HASH, 1).get();
        DBCursor result = db.getCollection(collectionName).find(null, fields)
                .sort(new BasicDBObject("$natural", -1)).limit(maxCount);
        List<DBObject> all = result.toArray();

        Messages messages = new Messages();
        for (DBObject dbObject : all) {
            Message message = new Message();
            message.setId(dbObject.get("_id").toString());
            DateTime dateTime = ISODateTimeFormat.dateTime().parseDateTime((String) dbObject.get("time"));
            message.setDate(dateTime);
            message.setPseudo((String) dbObject.get(MongoDBConstants.CHAT_PROP_USER));
            message.setText((String) dbObject.get(MongoDBConstants.CHAT_PROP_TEXT));
            message.setEmailHash((String) dbObject.get(MongoDBConstants.CHAT_PROP_EMAIL_HASH));

            messages.getMessages().add(message);
        }
        return messages;
    }

    @Override
    public Long getLastMessageId(String chatRoomId) {
        try {
            Double value = (Double) db.getCollection(MongoDBConstants.COLLECTION_CHATROOMS)
                    .findOne(new BasicDBObject("_id", chatRoomId)).get("counter");
            return value.longValue();
        } catch (Exception e) {
            return -1L;
        }
    }

    @Override
    public List<Long> getLastMessageIds(List<String> chatRoomIds) {
        List<Long> returnValue = new ArrayList<Long>();
        for (String chatRoomId : chatRoomIds) {
            returnValue.add(getLastMessageId(chatRoomId));
        }
        return returnValue;
    }

    @Override
    public boolean allowAnonymousMessages(String chatRoomId) {
        try {
            Boolean refuseAnonymous = (Boolean) db.getCollection(MongoDBConstants.COLLECTION_CHATROOMS)
                    .findOne(new BasicDBObject("_id", chatRoomId)).get(MongoDBConstants.CHATROOM_REFUSE_ANONYMOUS);

            return !refuseAnonymous;
        } catch (Exception e) {
            return true;
        }
    }
}