001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2018 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero 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, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.webconsole.base.events;
020
021import com.fasterxml.jackson.databind.ObjectMapper;
022import com.fasterxml.jackson.databind.json.JsonMapper;
023import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
024import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
025import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
026import java.io.IOException;
027import java.io.Writer;
028import org.jgrapes.core.Event;
029import org.jgrapes.webconsole.base.JsonRpc;
030
031/**
032 * Events derived from this class are transformed to JSON messages
033 * that are sent to the web console page. They may only be fired
034 * on the {@link org.jgrapes.webconsole.base.ConsoleConnection#responsePipeline()}
035 * (usually with 
036 * {@link org.jgrapes.webconsole.base.ConsoleConnection#respond(org.jgrapes.core.Event)}).
037 */
038public abstract class ConsoleCommand extends Event<Void> {
039
040    /** The mapper. */
041    @SuppressWarnings("PMD.FieldNamingConventions")
042    protected static final ObjectMapper mapper = JsonMapper.builder()
043        .addModule(new ParameterNamesModule()).addModule(new Jdk8Module())
044        .addModule(new JavaTimeModule()).build();
045
046    /**
047     * Emits the 
048     * [JSON notification](https://www.jsonrpc.org/specification#notification)
049     * using the given writer. Derived classes usually simply call 
050     * {@link #emitJson(Writer, String, Object...)} with the method
051     * name and parameters.
052     * 
053     * @param writer the writer
054     */
055    public abstract void emitJson(Writer writer)
056            throws InterruptedException, IOException;
057
058    /**
059     * Creates a JSON notification from the given data.
060     * Closes the `writer`.
061     *
062     * @param writer the writer
063     * @param method the method
064     * @param params the params
065     * @throws IOException Signals that an I/O exception has occurred.
066     */
067    protected void emitJson(Writer writer, String method, Object... params)
068            throws IOException {
069        JsonRpc rpc = new JsonRpc(method);
070        if (params.length > 0) {
071            for (Object obj : params) {
072                rpc.addParam(obj);
073            }
074        }
075        mapper.writeValue(writer, rpc);
076        writer.flush();
077    }
078
079    /**
080     * Calls {@link #emitJson(Writer, String, Object...)} with the
081     * given method and parameters. Provided for backwards compatibility.
082     *
083     * @param writer the writer
084     * @param method the method
085     * @param params the params
086     * @throws IOException Signals that an I/O exception has occurred.
087     * @deprecated Use {@link #emitJson(Writer, String, Object...)} instead.
088     */
089    @Deprecated
090    @SuppressWarnings("PMD.LinguisticNaming")
091    protected void toJson(Writer writer, String method, Object... params)
092            throws IOException {
093        emitJson(writer, method, params);
094    }
095}