001package jmri.server.json.block;
002
003import static jmri.server.json.JSON.VALUE;
004import static jmri.server.json.block.JsonBlock.BLOCK;
005import static jmri.server.json.block.JsonBlock.BLOCKS;
006import static jmri.server.json.idtag.JsonIdTag.IDTAG;
007import static jmri.server.json.reporter.JsonReporter.REPORTER;
008
009import com.fasterxml.jackson.databind.JsonNode;
010import com.fasterxml.jackson.databind.ObjectMapper;
011import com.fasterxml.jackson.databind.node.ArrayNode;
012import com.fasterxml.jackson.databind.node.ObjectNode;
013import javax.servlet.http.HttpServletResponse;
014
015import jmri.BasicRosterEntry;
016import jmri.Block;
017import jmri.BlockManager;
018import jmri.InstanceManager;
019import jmri.JmriException;
020import jmri.NamedBean;
021import jmri.ProvidingManager;
022import jmri.Reporter;
023import jmri.ReporterManager;
024import jmri.Sensor;
025import jmri.SensorManager;
026import jmri.server.json.JSON;
027import jmri.server.json.JsonException;
028import jmri.server.json.JsonNamedBeanHttpService;
029import jmri.server.json.JsonRequest;
030import jmri.server.json.idtag.JsonIdTagHttpService;
031import jmri.server.json.reporter.JsonReporter;
032import jmri.server.json.reporter.JsonReporterHttpService;
033import jmri.server.json.roster.JsonRosterHttpService;
034import jmri.server.json.sensor.JsonSensor;
035
036/**
037 * @author mstevetodd Copyright 2018
038 * @author Randall Wood Copyright 2018, 2019
039 */
040public class JsonBlockHttpService extends JsonNamedBeanHttpService<Block> {
041
042    private JsonIdTagHttpService idTagService = new JsonIdTagHttpService(mapper);
043    private JsonReporterHttpService reporterService = new JsonReporterHttpService(mapper);
044    private JsonRosterHttpService rosterService = new JsonRosterHttpService(mapper);
045
046    public JsonBlockHttpService(ObjectMapper mapper) {
047        super(mapper);
048    }
049
050    @Override
051    public ObjectNode doGet(Block block, String name, String type, JsonRequest request) throws JsonException {
052        ObjectNode root = this.getNamedBean(block, name, getType(), request);
053        ObjectNode data = root.with(JSON.DATA);
054        switch (block.getState()) {
055            case Block.UNDETECTED:
056            case NamedBean.UNKNOWN:
057                data.put(JSON.STATE, JSON.UNKNOWN);
058                break;
059            default:
060                data.put(JSON.STATE, block.getState());
061        }
062        // set block value based on type stored there
063        Object bv = block.getValue();
064        if (bv == null) {
065            data.putNull(VALUE);
066        } else if (bv instanceof jmri.IdTag) {
067            ObjectNode idTagValue = idTagService.doGet((jmri.IdTag) bv, name, IDTAG, request);
068            data.set(VALUE, idTagValue);
069        } else if (bv instanceof jmri.Reporter) {
070            ObjectNode reporterValue = reporterService.doGet((jmri.Reporter) bv, name, REPORTER, request);
071            data.set(VALUE, reporterValue);
072        } else if (bv instanceof jmri.BasicRosterEntry) {
073            ObjectNode rosterValue = (ObjectNode) rosterService.getRosterEntry(request.locale, ((BasicRosterEntry) bv).getId(), request.id);
074            data.set(VALUE, rosterValue);
075        } else {
076            // send string for types not explicitly handled
077            data.put(VALUE, bv.toString());
078        }
079        data.put(JsonSensor.SENSOR, block.getSensor() != null ? block.getSensor().getSystemName() : null);
080        data.put(JsonReporter.REPORTER, block.getReporter() != null ? block.getReporter().getSystemName() : null);
081        data.put(JSON.SPEED, block.getBlockSpeed());
082        data.put(JsonBlock.CURVATURE, block.getCurvature());
083        data.put(JSON.DIRECTION, block.getDirection());
084        data.put(JSON.LENGTH, block.getLengthMm());
085        data.put(JsonBlock.PERMISSIVE, block.getPermissiveWorking());
086        data.put(JsonBlock.SPEED_LIMIT, block.getSpeedLimit());
087        ArrayNode array = data.putArray(JsonBlock.DENIED);
088        block.getDeniedBlocks().forEach(array::add);
089        return root;
090    }
091
092    @Override
093    public ObjectNode doPost(Block block, String name, String type, JsonNode data, JsonRequest request)
094            throws JsonException {
095        if (!data.path(JSON.VALUE).isMissingNode()) {
096            if (data.path(JSON.VALUE).isNull()) {
097                block.setValue(null);
098            } else {
099                block.setValue(data.path(JSON.VALUE).asText());
100            }
101        }
102        int state = data.path(JSON.STATE).asInt(JSON.UNKNOWN);
103        switch (state) {
104            case JSON.ACTIVE:
105                block.setState(Block.OCCUPIED);
106                break;
107            case JSON.INACTIVE:
108                block.setState(Block.UNOCCUPIED);
109                break;
110            case JSON.UNKNOWN:
111                // leave state alone in this case
112                break;
113            default:
114                throw new JsonException(400, Bundle.getMessage(request.locale, "ErrorUnknownState", BLOCK, state),
115                        request.id);
116        }
117        if (!data.path(JsonSensor.SENSOR).isMissingNode()) {
118            JsonNode node = data.path(JsonSensor.SENSOR);
119            if (node.isNull()) {
120                block.setSensor(null);
121            } else {
122                Sensor sensor = InstanceManager.getDefault(SensorManager.class).getBySystemName(node.asText());
123                if (sensor != null) {
124                    block.setSensor(sensor.getSystemName());
125                } else {
126                    throw new JsonException(404,
127                            Bundle.getMessage(request.locale, JsonException.ERROR_NOT_FOUND, JsonSensor.SENSOR,
128                                    node.asText()),
129                            request.id);
130                }
131            }
132        }
133        if (!data.path(JsonReporter.REPORTER).isMissingNode()) {
134            JsonNode node = data.path(JsonReporter.REPORTER);
135            if (node.isNull()) {
136                block.setReporter(null);
137            } else {
138                Reporter reporter = InstanceManager.getDefault(ReporterManager.class).getBySystemName(node.asText());
139                if (reporter != null) {
140                    block.setReporter(reporter);
141                } else {
142                    throw new JsonException(404,
143                            Bundle.getMessage(request.locale, JsonException.ERROR_NOT_FOUND, JsonReporter.REPORTER,
144                                    node.asText()),
145                            request.id);
146                }
147            }
148        }
149        String text = data.findPath(JSON.SPEED).asText(block.getBlockSpeed());
150        try {
151            block.setBlockSpeed(text);
152        } catch (JmriException ex) {
153            throw new JsonException(HttpServletResponse.SC_BAD_REQUEST,
154                    Bundle.getMessage(request.locale, JsonException.ERROR_BAD_PROPERTY_VALUE, text, JSON.SPEED, type),
155                    request.id);
156        }
157        block.setCurvature(data.path(JsonBlock.CURVATURE).asInt(block.getCurvature()));
158        block.setDirection(data.path(JSON.DIRECTION).asInt(block.getDirection()));
159        if (data.path(JSON.LENGTH).isNumber()) {
160            block.setLength(data.path(JSON.LENGTH).floatValue());
161        }
162        block.setPermissiveWorking(data.path(JsonBlock.PERMISSIVE).asBoolean(block.getPermissiveWorking()));
163        return this.doGet(block, name, type, request);
164    }
165
166    @Override
167    protected void doDelete(Block bean, String name, String type, JsonNode data, JsonRequest request)
168            throws JsonException {
169        deleteBean(bean, name, type, data, request);
170    }
171
172    @Override
173    public JsonNode doSchema(String type, boolean server, JsonRequest request) throws JsonException {
174        switch (type) {
175            case BLOCK:
176            case BLOCKS:
177                return doSchema(type,
178                        server,
179                        "jmri/server/json/block/block-server.json",
180                        "jmri/server/json/block/block-client.json",
181                        request.id);
182            default:
183                throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
184                        Bundle.getMessage(request.locale, JsonException.ERROR_UNKNOWN_TYPE, type), request.id);
185        }
186    }
187
188    @Override
189    protected String getType() {
190        return BLOCK;
191    }
192
193    @Override
194    protected ProvidingManager<Block> getProvidingManager() {
195        return InstanceManager.getDefault(BlockManager.class);
196    }
197
198}