001package jmri.server.json.signalhead;
002
003import static jmri.server.json.JSON.APPEARANCE;
004import static jmri.server.json.JSON.APPEARANCE_NAME;
005import static jmri.server.json.JSON.DATA;
006import static jmri.server.json.JSON.LIT;
007import static jmri.server.json.JSON.STATE;
008import static jmri.server.json.JSON.TOKEN_HELD;
009import static jmri.server.json.signalhead.JsonSignalHead.SIGNAL_HEAD;
010import static jmri.server.json.signalhead.JsonSignalHead.SIGNAL_HEADS;
011
012import com.fasterxml.jackson.databind.JsonNode;
013import com.fasterxml.jackson.databind.ObjectMapper;
014import com.fasterxml.jackson.databind.node.ArrayNode;
015import com.fasterxml.jackson.databind.node.ObjectNode;
016import javax.servlet.http.HttpServletResponse;
017import jmri.InstanceManager;
018import jmri.SignalHead;
019import jmri.SignalHeadManager;
020import jmri.server.json.JSON;
021import jmri.server.json.JsonException;
022import jmri.server.json.JsonNonProvidedNamedBeanHttpService;
023import jmri.server.json.JsonRequest;
024
025/**
026 * JSON HTTP service for {@link jmri.SignalHead}s.
027 *
028 * @author Randall Wood Copyright 2016, 2018
029 */
030public class JsonSignalHeadHttpService extends JsonNonProvidedNamedBeanHttpService<SignalHead> {
031
032    public JsonSignalHeadHttpService(ObjectMapper mapper) {
033        super(mapper);
034    }
035
036    @Override
037    public JsonNode doGet(String type, String name, JsonNode data, JsonRequest request) throws JsonException {
038        return doGet(InstanceManager.getDefault(jmri.SignalHeadManager.class).getSignalHead(name), name, type, request);
039    }
040
041    @Override
042    protected ObjectNode doGet(SignalHead signalHead, String name, String type, JsonRequest request) throws JsonException {
043        ObjectNode root = this.getNamedBean(signalHead, name, type, request); // throws JsonException if signalHead == null
044        ObjectNode data = root.with(DATA);
045        if (signalHead != null) {
046            data.put(LIT, signalHead.getLit());
047            data.put(APPEARANCE, signalHead.getAppearance());
048            data.put(TOKEN_HELD, signalHead.getHeld());
049            //state is appearance, plus a flag for held status
050            if (signalHead.getHeld()) {
051                data.put(STATE, SignalHead.HELD);
052            } else {
053                data.put(STATE, signalHead.getAppearance());
054            }
055            data.put(APPEARANCE_NAME, signalHead.getAppearanceName());
056        }
057        return root;
058    }
059
060    @Override
061    public JsonNode doPost(String type, String name, JsonNode data, JsonRequest request) throws JsonException {
062        SignalHead signalHead = this.postNamedBean(InstanceManager.getDefault(jmri.SignalHeadManager.class).getSignalHead(name), data, name, type, request);
063        if (data.path(STATE).isIntegralNumber()) {
064            int state = data.path(STATE).asInt();
065            if (state == SignalHead.HELD) {
066                signalHead.setHeld(true);
067            } else {
068                boolean isValid = false;
069                for (int validState : signalHead.getValidStates()) {
070                    if (state == validState) {
071                        isValid = true;
072                        // TODO: completely insulate JSON state from SignalHead state
073                        if (signalHead.getHeld()) {
074                            signalHead.setHeld(false);
075                        }
076                        signalHead.setAppearance(state);
077                        break;
078                    }
079                }
080                if (!isValid) {
081                    throw new JsonException(400, Bundle.getMessage(request.locale, "ErrorUnknownState", SIGNAL_HEAD, state), request.id);
082                }
083            }
084        }
085        return this.doGet(type, name, data, request);
086    }
087
088    @Override
089    public JsonNode doGetList(String type, JsonNode data, JsonRequest request) throws JsonException {
090        ArrayNode array = this.mapper.createArrayNode();
091        for (SignalHead head : InstanceManager.getDefault(SignalHeadManager.class).getNamedBeanSet()) {
092            String name = head.getSystemName();
093            array.add(this.doGet(SIGNAL_HEAD, name, data, request));
094        }
095        return message(array, request.id);
096    }
097
098    @Override
099    public JsonNode doSchema(String type, boolean server, JsonRequest request) throws JsonException {
100        switch (type) {
101            case SIGNAL_HEAD:
102            case SIGNAL_HEADS:
103                return doSchema(type,
104                        server,
105                        "jmri/server/json/signalhead/signalHead-server.json",
106                        "jmri/server/json/signalhead/signalHead-client.json",
107                        request.id);
108            default:
109                throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, Bundle.getMessage(request.locale, JsonException.ERROR_UNKNOWN_TYPE, type), request.id);
110        }
111    }
112
113    @Override
114    public SignalHead getNamedBean(String type, String name, JsonNode data, JsonRequest request) throws JsonException {
115        try {
116            if (!data.isEmpty() && !data.isNull()) {
117                if (JSON.PUT.equals(request.method)) {
118                    doPut(type, name, data, request);
119                } else if (JSON.POST.equals(request.method)) {
120                    doPost(type, name, data, request);
121                }
122            }
123            return InstanceManager.getDefault(SignalHeadManager.class).getBySystemName(name);
124        } catch (IllegalArgumentException ex) {
125            throw new JsonException(HttpServletResponse.SC_BAD_REQUEST, Bundle.getMessage(request.locale, "ErrorInvalidSystemName", name, type), request.id);
126        }
127    }
128}