001package jmri.server.json.util;
002
003import com.fasterxml.jackson.databind.JsonNode;
004import java.beans.PropertyChangeEvent;
005import java.beans.PropertyChangeListener;
006import java.io.IOException;
007import jmri.InstanceManager;
008import jmri.JmriException;
009import jmri.server.json.JSON;
010import jmri.server.json.JsonConnection;
011import jmri.server.json.JsonException;
012import jmri.server.json.JsonRequest;
013import jmri.server.json.JsonSocketService;
014import jmri.web.server.WebServerPreferences;
015
016/**
017 *
018 * @author Randall Wood
019 */
020public class JsonUtilSocketService extends JsonSocketService<JsonUtilHttpService> {
021
022    private PropertyChangeListener rrNameListener;
023
024    public JsonUtilSocketService(JsonConnection connection) {
025        super(connection, new JsonUtilHttpService(connection.getObjectMapper()));
026    }
027
028    /**
029     * Package protected method for unit testing that allows a test HTTP service
030     * to be used.
031     * 
032     * @param connection the connection to use
033     * @param service    the supporting HTTP service
034     */
035    JsonUtilSocketService(JsonConnection connection, JsonUtilHttpService service) {
036        super(connection, service);
037    }
038
039    @Override
040    public void onMessage(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException {
041        String name = data.path(JSON.NAME).asText();
042        switch (type) {
043            case JSON.LOCALE:
044                // do nothing - we only want to prevent an error at this point
045                break;
046            case JSON.PING:
047                this.connection.sendMessage(this.connection.getObjectMapper().createObjectNode().put(JSON.TYPE, JSON.PONG), request.id);
048                break;
049            case JSON.GOODBYE:
050                this.connection.sendMessage(this.connection.getObjectMapper().createObjectNode().put(JSON.TYPE, JSON.GOODBYE), request.id);
051                break;
052            case JSON.RAILROAD:
053                this.connection.sendMessage(this.service.doGet(type, name, data, request), request.id);
054                this.rrNameListener = (PropertyChangeEvent evt) -> {
055                    try {
056                        this.handleRailroadChange();
057                    } catch (IOException ex) {
058                        InstanceManager.getDefault(WebServerPreferences.class).removePropertyChangeListener(this.rrNameListener);
059                    }
060                };
061                InstanceManager.getOptionalDefault(WebServerPreferences.class).ifPresent(preferences -> preferences.addPropertyChangeListener(this.rrNameListener));
062                break;
063            default:
064                this.connection.sendMessage(this.service.doPost(type, name, data, request), request.id);
065                break;
066        }
067    }
068
069    @Override
070    public void onList(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException {
071        this.connection.sendMessage(this.service.doGetList(type, data, request), request.id);
072    }
073
074    @Override
075    public void onClose() {
076        InstanceManager.getOptionalDefault(WebServerPreferences.class).ifPresent(preferences -> preferences.removePropertyChangeListener(this.rrNameListener));
077    }
078
079    private void handleRailroadChange() throws IOException {
080        try {
081            connection.sendMessage(service.doGet(JSON.RAILROAD, null, connection.getObjectMapper().createObjectNode(), new JsonRequest(this.connection.getLocale(), JSON.V5, JSON.GET, 0)), 0);
082        } catch (JsonException ex) {
083            this.connection.sendMessage(ex.getJsonMessage(), 0);
084        }
085    }
086}