001package jmri.server.json.message;
002
003import com.fasterxml.jackson.databind.JsonNode;
004import com.fasterxml.jackson.databind.ObjectMapper;
005import com.fasterxml.jackson.databind.node.ObjectNode;
006import java.util.Locale;
007import javax.annotation.Nonnull;
008import javax.annotation.CheckForNull;
009import jmri.InstanceManager;
010import jmri.server.json.JSON;
011import jmri.server.json.JsonHttpService;
012
013/**
014 * A message to be sent by the JMRI JSON message service.
015 *
016 * @author Randall Wood Copyright 2017
017 */
018public class JsonMessage {
019
020    /**
021     * {@value #CLIENT}
022     */
023    public static final String CLIENT = "client"; // NOI18N
024    /**
025     * {@value #MESSAGE}
026     */
027    public static final String MESSAGE = "message"; // NOI18N
028    /**
029     * {@value #CONTEXT}
030     */
031    public static final String CONTEXT = "context"; // NOI18N
032
033    private final String message;
034    private final Locale locale;
035    private final String client;
036    private final JsonNode context;
037    private final TYPE type;
038
039    public static enum TYPE {
040        INFO("info"),
041        SUCCESS("success"),
042        WARNING("warning"),
043        ERROR("error");
044
045        private final String message;
046
047        private TYPE(String message) {
048            this.message = message;
049        }
050
051        @Override
052        public String toString() {
053            return message;
054        }
055    }
056
057    /**
058     * Create a message with an {@link TYPE#INFO} type to be sent to all JSON
059     * clients.
060     *
061     * @param message the message to send
062     * @param locale  the locale of the message
063     */
064    public JsonMessage(@Nonnull String message, @Nonnull Locale locale) {
065        this(TYPE.INFO, message, null, null, locale);
066    }
067
068    /**
069     * Create a message to be sent to all JSON clients.
070     *
071     * @param type    the message type
072     * @param message the message to send
073     * @param locale  the locale of the message
074     */
075    public JsonMessage(TYPE type, @Nonnull String message, @Nonnull Locale locale) {
076        this(type, message, null, null, locale);
077    }
078
079    /**
080     * Create a message to be sent to the specified JSON client.
081     *
082     * @param type    the message type
083     * @param message the message to send
084     * @param client  the client to send the message to; if null, the message is
085     *                sent to all clients
086     * @param locale  the locale of the message
087     */
088    public JsonMessage(TYPE type, @Nonnull String message, @CheckForNull String client, @Nonnull Locale locale) {
089        this(type, message, client, null, locale);
090    }
091
092    /**
093     * Create a message to be sent to the specified JSON client with the
094     * specified context.
095     *
096     * @param type    the message type
097     * @param message the message to send
098     * @param client  the client to send the message to; if null, the message is
099     *                sent to all clients
100     * @param context the context for the message; if null, no context is sent
101     * @param locale  the locale of the message
102     */
103    public JsonMessage(TYPE type, @Nonnull String message, @CheckForNull String client, @CheckForNull JsonNode context, @Nonnull Locale locale) {
104        this.type = type;
105        this.message = message;
106        this.locale = locale;
107        this.client = client;
108        this.context = (context != null && context.isObject()) ? context : null;
109    }
110
111    /**
112     * Send the message using the default
113     * {@link jmri.server.json.message.JsonMessageClientManager}.
114     * <p>
115     * To send a message to an alternate JsonMessageClientManager, call that
116     * manager's
117     * {@link jmri.server.json.message.JsonMessageClientManager#send(jmri.server.json.message.JsonMessage)}
118     * method.
119     */
120    public void send() {
121        InstanceManager.getDefault(JsonMessageClientManager.class).send(this);
122    }
123
124    public String getClient() {
125        return this.client;
126    }
127
128    public JsonNode getContext() {
129        return this.context;
130    }
131
132    public String getMessage() {
133        return this.message;
134    }
135
136    public Locale getLocale() {
137        return this.locale;
138    }
139
140    /**
141     * Get the JSON token for each of the message types used in the
142     * constructors.
143     *
144     * @return the token value
145     */
146    public String getType() {
147        if (type == null) return TYPE.INFO.message;
148        return this.type.message;
149    }
150
151    /**
152     * Create a JSON node from this message.
153     *
154     * @param mapper the instance used to create raw JSON nodes
155     * @return the JSON node
156     */
157    public JsonNode toJSON(ObjectMapper mapper) {
158        ObjectNode data = mapper.createObjectNode();
159        data.put(MESSAGE, this.getMessage());
160        if (this.getContext() != null) {
161            data.set(CONTEXT, this.getContext());
162        } else {
163            data.putNull(CONTEXT);
164        }
165        data.put(JSON.TYPE, this.getType());
166        data.put(JSON.LOCALE, this.getLocale().toLanguageTag());
167        return JsonHttpService.message(mapper, MESSAGE, data, null, 0);
168    }
169}