class UDPNotificationHandler extends Handler<DatagramPacket> {

    @Override
    public void handleMessage(DatagramPacket packet) {
        Map receivedMsg = null;
        Map<String,Object> sendMsg = new LinkedHashMap<>();
        if (bytesLocation != null || regexPattern != null) {
            // Can't be parsed with Object mapper 
        }
        else if (expectingCsv) {
            try  {
                List<Object> csv = mapper.readerFor(List.class).with(CsvSchema.emptySchema().withHeader())
                        .readValue(packet.getData());
                client.sendNotification(csv);
            }
            catch (Exception e){
                log.warn("Failed to interpret UDP message as CSV.", e);
            }
            return;
        }
        else{
            try {
                receivedMsg = mapper.readValue(packet.getData(), Map.class);
            } 
            catch (Exception e) {
                if (expectingXml) {
                    log.warn("Failed to interpret UDP message as a XML object.", e);
                }
                else {  // expecting JSON
                    log.warn("Failed to interpret UDP message as a JSON object.", e);
                }
                return;
            }
        }
        

        // Transforms the message as requested by the Configuration document
        if (regexPattern != null) {
            
            // Create a String from the byte data, but remove unused bytes
            String recString = new String(packet.getData());
            int endIndex = recString.indexOf("\0");
            if (endIndex == -1) {endIndex = packet.getData().length;}
            recString = new String(packet.getData(), 0, endIndex, Charset.forName("UTF-8"));
            
            sendMsg = getRegexResults(recString);
        }
        else if (bytesLocation != null) {
            // Create a String from the byte data, but remove unused bytes
            String recString = new String(packet.getData());
            int endIndex = recString.indexOf("\0");
            if (endIndex == -1) {endIndex = packet.getData().length;}
            recString = new String(packet.getData(), 0, endIndex, Charset.forName("UTF-8"));
            
            MapTransformer.createTransformVal(sendMsg, bytesLocation, recString);
        }
        else if (passingPureMap) {
            sendMsg = receivedMsg;
        }
        else if (passingUnspecified) {
            // Set the messages to the same map so any untransformed values stay, and tell it to destroy any values removed
            sendMsg = receivedMsg;
            if (this.transformer != null) {
                this.transformer.transform(receivedMsg, sendMsg, true);
            }
        }
        else if (transformer == null) {
            // This means that no transform was specified and neither were any pass___ parameters in which case
            // the design decision is to send an empty Map, so the source is notified that a UDP message was received
            sendMsg = new LinkedHashMap<>();
        }
        else {
            this.transformer.transform(receivedMsg, sendMsg, false);
        }

        if (expectingXml && xmlRootLoc != null) {
            try {
                FromXmlParser p = (FromXmlParser) mapper.getFactory().createParser(packet.getData());
                MapTransformer.createTransformVal(sendMsg, xmlRootLoc, p.getStaxReader().getLocalName());
            }
            catch (Exception e) {
                log.error("Failed to interpret name of root", e);
            }
        }
        
        // Add the address and port that the packet came from if the config demands it
        if (recAddressKey != null) {
            MapTransformer.createTransformVal(sendMsg, recAddressKey, packet.getAddress().getHostAddress());
        }
        if (recPortKey != null) {
            MapTransformer.createTransformVal(sendMsg, recPortKey, packet.getPort());
        }

        client.sendNotification(sendMsg);
    }

    public  UDPNotificationHandler(Map incoming, ExtensionWebSocketClient client);

}