001package jmri.server.json.turnout;
002
003import static jmri.server.json.JSON.CLOSED;
004import static jmri.server.json.JSON.INCONSISTENT;
005import static jmri.server.json.JSON.INVERTED;
006import static jmri.server.json.JSON.STATE;
007import static jmri.server.json.JSON.THROWN;
008import static jmri.server.json.JSON.UNKNOWN;
009import static jmri.server.json.sensor.JsonSensor.SENSOR;
010import static jmri.server.json.turnout.JsonTurnout.FEEDBACK_MODE;
011import static jmri.server.json.turnout.JsonTurnout.FEEDBACK_MODES;
012import static jmri.server.json.turnout.JsonTurnout.TURNOUT;
013import static jmri.server.json.turnout.JsonTurnout.TURNOUTS;
014
015import com.fasterxml.jackson.databind.JsonNode;
016import com.fasterxml.jackson.databind.ObjectMapper;
017import com.fasterxml.jackson.databind.node.ArrayNode;
018import com.fasterxml.jackson.databind.node.ObjectNode;
019
020import javax.annotation.Nonnull;
021import javax.servlet.http.HttpServletResponse;
022import jmri.InstanceManager;
023import jmri.JmriException;
024import jmri.NamedBean;
025import jmri.ProvidingManager;
026import jmri.Sensor;
027import jmri.Turnout;
028import jmri.TurnoutManager;
029import jmri.server.json.JSON;
030import jmri.server.json.JsonException;
031import jmri.server.json.JsonNamedBeanHttpService;
032import jmri.server.json.JsonRequest;
033import jmri.server.json.sensor.JsonSensor;
034import jmri.server.json.sensor.JsonSensorHttpService;
035
036/**
037 *
038 * @author Randall Wood
039 */
040public class JsonTurnoutHttpService extends JsonNamedBeanHttpService<Turnout> {
041
042    private final JsonSensorHttpService sensorService;
043
044    public JsonTurnoutHttpService(ObjectMapper mapper) {
045        super(mapper);
046        sensorService = new JsonSensorHttpService(mapper);
047    }
048
049    @Override
050    public ObjectNode doGet(Turnout turnout, String name, String type, JsonRequest request) throws JsonException {
051        ObjectNode root = this.getNamedBean(turnout, name, getType(), request); // throws JsonException if turnout == null
052        ObjectNode data = root.with(JSON.DATA);
053        if (turnout != null) {
054            data.put(INVERTED, turnout.getInverted());
055            switch (turnout.getKnownState()) {
056                case Turnout.THROWN:
057                    data.put(STATE, THROWN);
058                    break;
059                case Turnout.CLOSED:
060                    data.put(STATE, CLOSED);
061                    break;
062                case NamedBean.INCONSISTENT:
063                    data.put(STATE, INCONSISTENT);
064                    break;
065                case NamedBean.UNKNOWN:
066                default:
067                    data.put(STATE, UNKNOWN);
068                    break;
069            }
070            data.put(FEEDBACK_MODE, turnout.getFeedbackMode());
071            ArrayNode modes = data.arrayNode();
072            turnout.getValidFeedbackModes().forEach(modes::add);
073            data.set(FEEDBACK_MODES, modes);
074            ArrayNode sensors = data.arrayNode();
075            Sensor sensor = turnout.getFirstSensor();
076            sensors.add(sensor == null ? null : sensorService.doGet(sensor, sensor.getSystemName(), JsonSensor.SENSOR, request));
077            sensor = turnout.getSecondSensor();
078            sensors.add(sensor == null ? null : sensorService.doGet(sensor, sensor.getSystemName(), JsonSensor.SENSOR, request));
079            data.set(SENSOR, sensors);
080        }
081        return root;
082    }
083
084    @Override
085    public ObjectNode doPost(Turnout turnout, String name, String type, JsonNode data, JsonRequest request) throws JsonException {
086        if (data.path(SENSOR).isArray()) {
087            int number = 0;
088            for (JsonNode node : data.path(SENSOR)) {
089                if (node != null) {
090                    this.addSensorToTurnout(turnout, node, number, request);
091                }
092                number++;
093            }
094        }
095        if (data.path(FEEDBACK_MODE).isInt()) {
096            try {
097                turnout.setFeedbackMode(data.path(FEEDBACK_MODE).asInt());
098            } catch (IllegalArgumentException ex) {
099                throw new JsonException(400, Bundle.getMessage(request.locale, "ErrorInvalidProperty", FEEDBACK_MODE, type, name), request.id);
100            }
101        }
102        if (data.path(INVERTED).isBoolean()) {
103            turnout.setInverted(data.path(INVERTED).asBoolean());
104        }
105        turnout.setInverted(data.path(INVERTED).asBoolean(turnout.getInverted()));
106        int state = data.path(STATE).asInt(UNKNOWN);
107        switch (state) {
108            case THROWN:
109                turnout.setCommandedState(Turnout.THROWN);
110                break;
111            case CLOSED:
112                turnout.setCommandedState(Turnout.CLOSED);
113                break;
114            case UNKNOWN:
115                // leave state alone in this case
116                break;
117            default:
118                throw new JsonException(400, Bundle.getMessage(request.locale, "ErrorUnknownState", TURNOUT, state), request.id);
119        }
120        return this.doGet(turnout, name, type, request);
121    }
122
123    private void addSensorToTurnout(@Nonnull Turnout turnout, @Nonnull JsonNode data, int number, @Nonnull JsonRequest request) throws JsonException {
124        try {
125            if (data.isNull()) {
126                turnout.provideFeedbackSensor(null, number);
127            } else {
128                Sensor sensor = null;
129                if (data.isTextual()) {
130                    sensor = sensorService.getNamedBean(SENSOR, data.asText(), mapper.nullNode(), request);
131                } else if (data.isObject()) {
132                    sensor = sensorService.getNamedBean(SENSOR, data.path(JSON.NAME).asText(), data, request);
133                } else {
134                    throw new JsonException(400, Bundle.getMessage(request.locale, "ErrorInvalidProperty", SENSOR, TURNOUT, turnout.getSystemName()), request.id);
135                }
136                if (sensor != null) {
137                    turnout.provideFeedbackSensor(sensor.getSystemName(), number);
138                } else {
139                    throw new JsonException(404,
140                            Bundle.getMessage(request.locale, "ErrorNotFound", SENSOR, data.asText()), request.id);
141                }
142            }
143        } catch (JmriException ex) {
144            throw new JsonException(500, Bundle.getMessage(request.locale, "ErrorInternal", TURNOUT), request.id);
145        }
146    }
147
148    @Override
149    protected void doDelete(Turnout bean, String name, String type, JsonNode data, JsonRequest request)
150            throws JsonException {
151        deleteBean(bean, name, type, data, request);
152    }
153
154    @Override
155    public JsonNode doSchema(String type, boolean server, JsonRequest request) throws JsonException {
156        switch (type) {
157            case TURNOUT:
158            case TURNOUTS:
159                return doSchema(type,
160                        server,
161                        "jmri/server/json/turnout/turnout-server.json",
162                        "jmri/server/json/turnout/turnout-client.json",
163                        request.id);
164            default:
165                throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, Bundle.getMessage(request.locale, JsonException.ERROR_UNKNOWN_TYPE, type), request.id);
166        }
167    }
168
169    @Override
170    protected String getType() {
171        return TURNOUT;
172    }
173
174    @Override
175    protected ProvidingManager<Turnout> getProvidingManager() {
176        return InstanceManager.getDefault(TurnoutManager.class);
177    }
178}