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        if (data.path(LIT).isTextual()) {
086            signalHead.setLit(data.path(LIT).asBoolean());            
087        }
088        if (data.path(TOKEN_HELD).isTextual()) {
089            signalHead.setHeld(data.path(TOKEN_HELD).asBoolean());            
090        }        
091        return this.doGet(type, name, data, request);
092    }
093
094    @Override
095    public JsonNode doGetList(String type, JsonNode data, JsonRequest request) throws JsonException {
096        ArrayNode array = this.mapper.createArrayNode();
097        for (SignalHead head : InstanceManager.getDefault(SignalHeadManager.class).getNamedBeanSet()) {
098            String name = head.getSystemName();
099            array.add(this.doGet(SIGNAL_HEAD, name, data, request));
100        }
101        return message(array, request.id);
102    }
103
104    @Override
105    public JsonNode doSchema(String type, boolean server, JsonRequest request) throws JsonException {
106        switch (type) {
107            case SIGNAL_HEAD:
108            case SIGNAL_HEADS:
109                return doSchema(type,
110                        server,
111                        "jmri/server/json/signalhead/signalHead-server.json",
112                        "jmri/server/json/signalhead/signalHead-client.json",
113                        request.id);
114            default:
115                throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, Bundle.getMessage(request.locale, JsonException.ERROR_UNKNOWN_TYPE, type), request.id);
116        }
117    }
118
119    @Override
120    public SignalHead getNamedBean(String type, String name, JsonNode data, JsonRequest request) throws JsonException {
121        try {
122            if (!data.isEmpty() && !data.isNull()) {
123                if (JSON.PUT.equals(request.method)) {
124                    doPut(type, name, data, request);
125                } else if (JSON.POST.equals(request.method)) {
126                    doPost(type, name, data, request);
127                }
128            }
129            return InstanceManager.getDefault(SignalHeadManager.class).getBySystemName(name);
130        } catch (IllegalArgumentException ex) {
131            throw new JsonException(HttpServletResponse.SC_BAD_REQUEST, Bundle.getMessage(request.locale, "ErrorInvalidSystemName", name, type), request.id);
132        }
133    }
134}