001/*
002 * Syncany, www.syncany.org
003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com>
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package org.syncany.operations.daemon.messages.api;
019
020import java.util.logging.Level;
021
022import com.google.common.base.Optional;
023import com.google.common.collect.Iterables;
024import com.google.gson.Gson;
025import com.google.gson.JsonElement;
026import com.google.gson.JsonObject;
027import com.google.gson.JsonParser;
028
029/**
030 * @author Christian Roth (christian.roth@port17.de)
031 */
032public abstract class JsonMessageFactory extends MessageFactory {
033        private static final Gson SERIALIZER = new Gson();
034        private static final JsonParser PARSER = new JsonParser();
035
036        public static Response toResponse(String responseMessageString) throws Exception {
037                Message responseMessage = toMessage(responseMessageString);
038
039                if (!(responseMessage instanceof Response)) {
040                        throw new Exception("Invalid class: Message is not a response type: " + responseMessage.getClass());
041                }
042
043                return (Response) responseMessage;
044        }
045
046        public static Request toRequest(String responseMessageString) throws Exception {
047                Message requestMessage = toMessage(responseMessageString);
048
049                if (!(requestMessage instanceof Request)) {
050                        throw new Exception("Invalid class: Message is not a request type:" + requestMessage.getClass());
051                }
052
053                return (Request) requestMessage;
054        }
055
056        public static Message toMessage(String messageStr) throws Exception {
057                String messageType = getMessageType(messageStr);
058                Class<? extends Message> messageClass = getMessageClass(messageType);
059
060                JsonObject result = PARSER.parse(messageStr).getAsJsonObject();
061                JsonElement serializedMessage = Optional.fromNullable(Iterables.get(result.entrySet(), 0).getValue()).or(new JsonObject());
062
063                Message message = SERIALIZER.fromJson(serializedMessage, messageClass);
064                logger.log(Level.INFO, "Message created: " + message);
065
066                return message;
067        }
068
069        public static String toJson(Message response) throws Exception {
070                JsonElement je = SERIALIZER.toJsonTree(response);
071                JsonObject jo = new JsonObject();
072                jo.add(response.getClass().getSimpleName(), je);
073                return jo.toString();
074        }
075
076        /** 
077         * Parses JSON message for message type. 
078         * First key contains message name:
079         * 
080         * <pre>
081         * { "messageType":
082         *   {
083         *     // payload
084         *   }
085         * }
086         * </pre>
087         */
088        private static String getMessageType(String message) throws Exception {
089                try {
090                        JsonObject result = PARSER.parse(message).getAsJsonObject();
091                        return Iterables.get(result.entrySet(), 0).getKey();
092                }
093                catch (Exception e) {
094                        throw new Exception("Cannot find type of message. Invalid JSON: " + message);
095                }
096        }
097}