001package jmri.server.json.consist;
002
003import com.fasterxml.jackson.databind.JsonNode;
004import java.io.IOException;
005import java.util.HashSet;
006import jmri.ConsistListListener;
007import jmri.ConsistListener;
008import jmri.DccLocoAddress;
009import jmri.JmriException;
010import jmri.LocoAddress;
011import jmri.jmrit.consisttool.ConsistFile;
012import jmri.server.json.JSON;
013import jmri.server.json.JsonConnection;
014import jmri.server.json.JsonException;
015import jmri.server.json.JsonRequest;
016import jmri.server.json.JsonSocketService;
017import org.slf4j.Logger;
018import org.slf4j.LoggerFactory;
019
020/**
021 *
022 * @author Randall Wood Copyright (C) 2016
023 */
024public class JsonConsistSocketService extends JsonSocketService<JsonConsistHttpService> {
025
026    private final HashSet<LocoAddress> consists = new HashSet<>();
027    private final JsonConsistListener consistListener = new JsonConsistListener();
028    private final JsonConsistListListener consistListListener = new JsonConsistListListener();
029    private static final Logger log = LoggerFactory.getLogger(JsonConsistSocketService.class);
030
031    public JsonConsistSocketService(JsonConnection connection) {
032        super(connection, new JsonConsistHttpService(connection.getObjectMapper()));
033        service.manager.addConsistListListener(consistListListener);
034    }
035
036    @Override
037    public void onMessage(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException {
038        if (JsonConsist.CONSISTS.equals(type)) {
039            connection.sendMessage(service.doGetList(type, data, request), request.id);
040        } else {
041            DccLocoAddress address = new DccLocoAddress(data.path(JSON.ADDRESS).asInt(), data.path(JSON.IS_LONG_ADDRESS).asBoolean());
042            String name = address.getNumber() + (address.isLongAddress() ? "L" : "");
043            if (request.method.equals(JSON.PUT)) {
044                connection.sendMessage(service.doPut(type, name, data, request), request.id);
045            } else {
046                connection.sendMessage(service.doPost(type, name, data, request), request.id);
047            }
048            if (!consists.contains(address)) {
049                service.manager.getConsist(address).addConsistListener(consistListener);
050                consists.add(address);
051            }
052        }
053    }
054
055    @Override
056    public void onList(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException {
057        connection.sendMessage(service.doGetList(type, data, request), request.id);
058    }
059
060    @Override
061    public void onClose() {
062        consists.stream().forEach(address -> service.manager.getConsist(address).removeConsistListener(consistListener));
063        consists.clear();
064        service.manager.removeConsistListListener(consistListListener);
065    }
066
067    private class JsonConsistListener implements ConsistListener {
068
069        @Override
070        public void consistReply(LocoAddress locoaddress, int status) {
071            try {
072                try {
073                    connection.sendMessage(service.getConsist(locoaddress, new JsonRequest(getLocale(), JSON.V5, JSON.GET, 0)), 0);
074                } catch (JsonException ex) {
075                    connection.sendMessage(ex.getJsonMessage(), 0);
076                }
077            } catch (IOException ex) {
078                // this IO execption caused by broken comms with client
079                service.manager.getConsist(locoaddress).removeConsistListener(this);
080                consists.remove(locoaddress);
081            }
082            try {
083                (new ConsistFile()).writeFile(service.manager.getConsistList());
084            } catch (IOException ex) {
085                // this IO execption caused by unable to write file
086                log.error("Unable to write consist file \"{}\"", ConsistFile.defaultConsistFilename(), ex);
087            }
088        }
089    }
090
091    private class JsonConsistListListener implements ConsistListListener {
092
093        @Override
094        public void notifyConsistListChanged() {
095            try {
096                try {
097                    connection.sendMessage(service.doGetList(JsonConsist.CONSISTS,
098                            service.getObjectMapper().createObjectNode(), new JsonRequest(getLocale(), getVersion(), JSON.GET, 0)), 0);
099                } catch (JsonException ex) {
100                    connection.sendMessage(ex.getJsonMessage(), 0);
101                }
102            } catch (IOException ex) {
103                // this IO exception caused by broken communications with client
104                service.manager.removeConsistListListener(this);
105            }
106            try {
107                (new ConsistFile()).writeFile(service.manager.getConsistList());
108            } catch (IOException ex) {
109                // this IO exception caused by unable to write file
110                log.error("Unable to write consist file \"{}\"", ConsistFile.defaultConsistFilename(), ex);
111            }
112        }
113    }
114}