001package jmri.server.json.layoutblock; 002 003import static jmri.server.json.JSON.DATA; 004import static jmri.server.json.JSON.STATE; 005import static jmri.server.json.JSON.USERNAME; 006import static jmri.server.json.layoutblock.JsonLayoutBlock.BLOCK_COLOR; 007import static jmri.server.json.layoutblock.JsonLayoutBlock.EXTRA_COLOR; 008import static jmri.server.json.layoutblock.JsonLayoutBlock.LAYOUTBLOCK; 009import static jmri.server.json.layoutblock.JsonLayoutBlock.LAYOUTBLOCKS; 010import static jmri.server.json.layoutblock.JsonLayoutBlock.OCCUPANCY_SENSOR; 011import static jmri.server.json.layoutblock.JsonLayoutBlock.OCCUPIED_COLOR; 012import static jmri.server.json.layoutblock.JsonLayoutBlock.OCCUPIED_SENSE; 013import static jmri.server.json.layoutblock.JsonLayoutBlock.TRACK_COLOR; 014import static jmri.server.json.layoutblock.JsonLayoutBlock.USE_EXTRA_COLOR; 015import static jmri.server.json.block.JsonBlock.BLOCK; 016import static jmri.server.json.memory.JsonMemory.MEMORY; 017import static jmri.server.json.sensor.JsonSensor.SENSOR; 018 019import com.fasterxml.jackson.databind.JsonNode; 020import com.fasterxml.jackson.databind.ObjectMapper; 021import com.fasterxml.jackson.databind.node.ArrayNode; 022import com.fasterxml.jackson.databind.node.ObjectNode; 023import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 024 025import java.awt.Color; 026import java.util.List; 027 028import javax.servlet.http.HttpServletResponse; 029 030import jmri.InstanceManager; 031import jmri.Memory; 032import jmri.MemoryManager; 033import jmri.Sensor; 034import jmri.SensorManager; 035import jmri.jmrit.display.layoutEditor.LayoutBlock; 036import jmri.jmrit.display.layoutEditor.LayoutBlockManager; 037import jmri.server.json.JSON; 038import jmri.server.json.JsonException; 039import jmri.server.json.JsonNonProvidedNamedBeanHttpService; 040import jmri.server.json.JsonRequest; 041import jmri.util.ColorUtil; 042 043/** 044 * 045 * @author mstevetodd Copyright (C) 2018 046 * @author Randall Wood 047 */ 048public class JsonLayoutBlockHttpService extends JsonNonProvidedNamedBeanHttpService<LayoutBlock> { 049 050 public JsonLayoutBlockHttpService(ObjectMapper mapper) { 051 super(mapper); 052 } 053 054 @Override 055 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "check here for null is complexity for a situation that should not be possible") 056 public JsonNode doGet(String type, String name, JsonNode data, JsonRequest request) throws JsonException { 057 return doGet(InstanceManager.getDefault(LayoutBlockManager.class).getBySystemName(name), name, type, request); 058 } 059 060 @Override 061 protected ObjectNode doGet(LayoutBlock layoutBlock, String name, String type, JsonRequest request) throws JsonException { 062 ObjectNode root = super.getNamedBean(layoutBlock, name, type, request); // throws JsonException if layoutBlock == null 063 ObjectNode data = root.with(DATA); 064 data.put(STATE, layoutBlock.getState()); 065 data.put(USE_EXTRA_COLOR, layoutBlock.getUseExtraColor()); 066 data.put(BLOCK_COLOR, ColorUtil.colorToColorName(layoutBlock.getBlockColor())); 067 data.put(TRACK_COLOR, ColorUtil.colorToColorName(layoutBlock.getBlockTrackColor())); 068 data.put(OCCUPIED_COLOR, ColorUtil.colorToColorName(layoutBlock.getBlockOccupiedColor())); 069 data.put(EXTRA_COLOR, ColorUtil.colorToColorName(layoutBlock.getBlockExtraColor())); 070 if (layoutBlock.getOccupancySensor() != null) { 071 data.put(OCCUPANCY_SENSOR, layoutBlock.getOccupancySensor().getSystemName()); 072 } else { 073 data.putNull(OCCUPANCY_SENSOR); 074 } 075 if (layoutBlock.getMemory() != null) { 076 data.put(MEMORY, layoutBlock.getMemory().getSystemName()); 077 } else { 078 data.putNull(MEMORY); 079 } 080 if (layoutBlock.getBlock() != null) { 081 data.put(BLOCK, layoutBlock.getBlock().getSystemName()); 082 } else { 083 data.putNull(BLOCK); 084 } 085 data.put(OCCUPIED_SENSE, layoutBlock.getOccupiedSense()); 086 return root; 087 } 088 089 @Override 090 public JsonNode doPost(String type, String name, JsonNode data, JsonRequest request) throws JsonException { 091 return doPost(InstanceManager.getDefault(LayoutBlockManager.class).getBySystemName(name), data, name, type, request); 092 } 093 094 public JsonNode doPost(LayoutBlock layoutBlock, JsonNode data, String name, String type, JsonRequest request) throws JsonException { 095 postNamedBean(layoutBlock, data, name, type, request); // throws JsonException if layoutBlock == null 096 setBlockTrackColor(layoutBlock, TRACK_COLOR, type, data, request); 097 setBlockTrackColor(layoutBlock, OCCUPIED_COLOR, type, data, request); 098 setBlockTrackColor(layoutBlock, EXTRA_COLOR, type, data, request); 099 String string = ""; 100 if (!data.path(MEMORY).isMissingNode()) { 101 string = !data.path(MEMORY).isNull() ? data.path(MEMORY).asText() : null; 102 if (string != null) { 103 Memory memory = InstanceManager.getDefault(MemoryManager.class).getBySystemName(string); 104 if (memory == null) { 105 throw new JsonException(HttpServletResponse.SC_NOT_FOUND, Bundle.getMessage(request.locale, JsonException.ERROR_NOT_FOUND, MEMORY, string), request.id); 106 } 107 layoutBlock.setMemoryName(memory.getUserName()); 108 } else { 109 layoutBlock.setMemoryName(null); 110 } 111 } 112 if (!data.path(OCCUPANCY_SENSOR).isMissingNode()) { 113 string = !data.path(OCCUPANCY_SENSOR).isNull() ? data.path(OCCUPANCY_SENSOR).asText() : null; 114 if (string != null) { 115 Sensor sensor = InstanceManager.getDefault(SensorManager.class).getBySystemName(string); 116 if (sensor == null) { 117 throw new JsonException(HttpServletResponse.SC_NOT_FOUND, Bundle.getMessage(request.locale, JsonException.ERROR_NOT_FOUND, SENSOR, string), request.id); 118 } 119 layoutBlock.setOccupancySensorName(sensor.getUserName()); 120 } else { 121 layoutBlock.setOccupancySensorName(null); 122 } 123 } 124 layoutBlock.setUseExtraColor(data.path(USE_EXTRA_COLOR).asBoolean(layoutBlock.getUseExtraColor())); 125 return doGet(layoutBlock, name, type, request); 126 } 127 128 private void setBlockTrackColor(LayoutBlock layoutBlock, String key, String type, JsonNode data, JsonRequest request) throws JsonException { 129 String value = ""; 130 try { 131 value = data.path(key).asText(); 132 Color color = (!data.path(key).isMissingNode() ? ColorUtil.stringToColor(value) : null); 133 if (color != null) { 134 layoutBlock.setBlockTrackColor(color); 135 } 136 } catch (IllegalArgumentException ex) { 137 throw new JsonException(HttpServletResponse.SC_BAD_REQUEST, Bundle.getMessage(request.locale, JsonException.ERROR_BAD_PROPERTY_VALUE, value, key, type), request.id); 138 } 139 } 140 141 @Override 142 public JsonNode doPut(String type, String name, JsonNode data, JsonRequest request) throws JsonException { 143 LayoutBlock layoutBlock = null; 144 String systemName = name; 145 // an empty name should be null to create a LayoutBlock with a generated systemName 146 // the name would come across as an empty string even if null in the JSON payload 147 // because JsonNode.asText() returns an empty String when JsonNode.isNull() == true 148 if (systemName.isEmpty()) { 149 systemName = null; 150 } 151 if (data.path(USERNAME).isMissingNode() || data.path(USERNAME).isNull()) { 152 layoutBlock = InstanceManager.getDefault(LayoutBlockManager.class).createNewLayoutBlock(); 153 } else { 154 String userName = data.path(USERNAME).asText(); 155 if (!userName.isEmpty()) { 156 layoutBlock = InstanceManager.getDefault(LayoutBlockManager.class).createNewLayoutBlock(systemName, userName); 157 } else { 158 throw new JsonException(HttpServletResponse.SC_BAD_REQUEST, Bundle.getMessage(request.locale, "ErrorEmptyAttribute", USERNAME, type), request.id); 159 } 160 } 161 if (layoutBlock == null) { 162 throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, Bundle.getMessage(request.locale, "ErrorInternal", type), request.id); 163 } 164 layoutBlock.initializeLayoutBlock(); 165 layoutBlock.initializeLayoutBlockRouting(); 166 return doPost(layoutBlock, data, name, type, request); 167 } 168 169 @Override 170 public void doDelete(String type, String name, JsonNode data, JsonRequest request) throws JsonException { 171 LayoutBlock layoutBlock = InstanceManager.getDefault(LayoutBlockManager.class).getBySystemName(name); 172 if (layoutBlock == null) { 173 throw new JsonException(HttpServletResponse.SC_NOT_FOUND, Bundle.getMessage(request.locale, JsonException.ERROR_NOT_FOUND, type, name), request.id); 174 } 175 List<String> listeners = layoutBlock.getListenerRefs(); 176 if (!listeners.isEmpty() && !acceptForceDeleteToken(type, name, data.path(JSON.FORCE_DELETE).asText())) { 177 ArrayNode conflicts = mapper.createArrayNode(); 178 listeners.forEach(conflicts::add); 179 throwDeleteConflictException(type, name, conflicts, request); 180 } else { 181 InstanceManager.getDefault(LayoutBlockManager.class).deregister(layoutBlock); 182 } 183 } 184 185 @Override 186 public JsonNode doGetList(String type, JsonNode data, JsonRequest request) throws JsonException { 187 return doGetList(InstanceManager.getDefault(LayoutBlockManager.class), LAYOUTBLOCK, data, request); 188 } 189 190 @Override 191 public JsonNode doSchema(String type, boolean server, JsonRequest request) throws JsonException { 192 switch (type) { 193 case LAYOUTBLOCK: 194 case LAYOUTBLOCKS: 195 return doSchema(type, 196 server, 197 "jmri/server/json/layoutblock/layoutBlock-server.json", 198 "jmri/server/json/layoutblock/layoutBlock-client.json", 199 request.id); 200 default: 201 throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, Bundle.getMessage(request.locale, JsonException.ERROR_UNKNOWN_TYPE, type), request.id); 202 } 203 } 204 205 @Override 206 public LayoutBlock getNamedBean(String type, String name, JsonNode data, JsonRequest request) throws JsonException { 207 try { 208 if (!data.isEmpty() && !data.isNull()) { 209 if (JSON.PUT.equals(request.method)) { 210 doPut(type, name, data, request); 211 } else if (JSON.POST.equals(request.method)) { 212 doPost(type, name, data, request); 213 } 214 } 215 return InstanceManager.getDefault(LayoutBlockManager.class).getBySystemName(name); 216 } catch (IllegalArgumentException ex) { 217 throw new JsonException(HttpServletResponse.SC_BAD_REQUEST, Bundle.getMessage(request.locale, "ErrorInvalidSystemName", name, type), request.id); 218 } 219 } 220}