/**
 *  Copyright © 2025, Luis Andrés Lange <https://javacomm.net>
 *
 *  Previously released under Apache License 2.0; now licensed under MPL 2.0.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *  ----------------------------------------------------------------------------
 *
 *  Exhibit B - "Incompatible With Secondary Licenses" Notice
 *
 *  This Source Code Form is "Incompatible With Secondary Licenses",
 *  as defined by the Mozilla Public License, v. 2.0.
 *
 *  In short:
 *  - This file may be used, modified, and distributed under MPL 2.0 only.
 *  - It may NOT be relicensed under GPL, LGPL, AGPL, or any other Secondary License.
 *
 *  Rationale:
 *  - Ensures that the code remains MPL-2.0.
 *  - Avoids legal conflicts with GPL-licensed libraries (e.g., VideoLAN).
 *  - Maximizes usability for commercial and security-critical applications.
 *
 */
package net.javacomm.protocol;

import static net.javacomm.protocol.HEADER.CONFIRM;
import static net.javacomm.protocol.HEADER.ERROR;
import static net.javacomm.protocol.HEADER.REQUEST;
import static net.javacomm.protocol.HEADER.RESPONSE;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
import jakarta.websocket.EndpointConfig;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.javacomm.multilingual.schema.KEY;



/**
 * Jeder eingehende <i>JSON</i> String wird über diese Klasse nach
 * {@link MESSAGE} dekodiert.
 * 
 * 
 * @author llange
 *
 */
public class MessageDecoder implements Decoder.Text<MESSAGE> {

  final static Logger log = LogManager.getLogger(MessageDecoder.class);

  @Override
  public MESSAGE decode(String message) throws DecodeException {
    if (message == null) throw new DecodeException(message, "message is null");
    try {
      Matcher matcher = Protocol.PATTERN_JSON.matcher(message);
      if (!matcher.matches()) {
        log.fatal("Protokollfehler:" + message);
        throw new DecodeException(message, "Die Nachricht entspricht nicht dem vereinbarten Protokoll");
      }
      MESSAGE decodedMessage = decodeCHATMESSAGE(message);
      if (decodedMessage instanceof CHATMESSAGE) return decodedMessage;

      decodedMessage = decodeCONFERENCEAUDIO(message);
      if (decodedMessage instanceof CONFERENCEAUDIO) return decodedMessage;

      decodedMessage = decodeNEWMOUSEPOINTER(message);
      if (decodedMessage instanceof NEWMOUSEPOINTER) return decodedMessage;

      decodedMessage = decodeNEWIMAGE(message);
      if (decodedMessage instanceof NEWIMAGE) return decodedMessage;

      decodedMessage = decodeCONFERENCEVIDEO(message);
      if (decodedMessage instanceof CONFERENCEVIDEO) return decodedMessage;

      decodedMessage = decodeSTOPSENDINGVIDEO(message);
      if (decodedMessage instanceof STOPSENDINGVIDEO) return decodedMessage;

      decodedMessage = decodeCONFERENCE(message);
      if (decodedMessage instanceof CONFERENCE) return decodedMessage;

      decodedMessage = decodeIMAGE(message);
      if (decodedMessage instanceof IMAGE) return decodedMessage;

      decodedMessage = decodeBEAMEROFF(message);
      if (decodedMessage instanceof BEAMEROFF) return decodedMessage;

      decodedMessage = decodeCONFERENCEMUTE(message);
      if (decodedMessage instanceof CONFERENCEMUTE) return decodedMessage;

      decodedMessage = decodePROYECTORCLOSING(message);
      if (decodedMessage instanceof PROYECTORCLOSING) return decodedMessage;

      decodedMessage = decodeSCREENCAST(message);
      if (decodedMessage instanceof SCREENCAST) return decodedMessage;

      decodedMessage = decodeUPDATEFILETYPES(message);
      if (decodedMessage instanceof UPDATEFILETYPES) return decodedMessage;

      decodedMessage = decodeFILETYPES(message);
      if (decodedMessage instanceof FILETYPES) return decodedMessage;

      decodedMessage = decodeMICROERROR(message);
      if (decodedMessage instanceof MICROERROR) return decodedMessage;

      decodedMessage = decodeREADROOMS(message);
      if (decodedMessage instanceof READROOMS) return decodedMessage;

      decodedMessage = decodeBREAKROOMS(message);
      if (decodedMessage instanceof BREAKROOMS) return decodedMessage;

      decodedMessage = decodeONHOOK(message);
      if (decodedMessage instanceof ONHOOK) return decodedMessage;

      decodedMessage = decodeUPDATEPHONE(message);
      if (decodedMessage instanceof UPDATEPHONE) return decodedMessage;

      decodedMessage = decodeONCALL(message);
      if (decodedMessage instanceof ONCALL) return decodedMessage;

      decodedMessage = decodeINCOMINGCALL(message);
      if (decodedMessage instanceof INCOMINGCALL) return decodedMessage;

      decodedMessage = decodeDIAL(message);
      if (decodedMessage instanceof DIAL) return decodedMessage;

      decodedMessage = decodeSEARCHFILES(message);
      if (decodedMessage instanceof SEARCHFILES) return decodedMessage;

      decodedMessage = decodeDOWNLOAD(message);
      if (decodedMessage instanceof DOWNLOAD) return decodedMessage;

      decodedMessage = decodeUPLOADFILES(message);
      if (decodedMessage instanceof UPLOADFILES) return decodedMessage;

      decodedMessage = decodeDELETEUPLOADFILES(message);
      if (decodedMessage instanceof DELETEUPLOADFILES) return decodedMessage;

      decodedMessage = decodeUPDATEPORT(message);
      if (decodedMessage instanceof UPDATEPORT) return decodedMessage;

      decodedMessage = decodePRIVATEMESSAGE(message);
      if (decodedMessage instanceof PRIVATEMESSAGE) return decodedMessage;

      decodedMessage = decodeKEEPALIVE(message);
      if (decodedMessage instanceof KEEPALIVE) return decodedMessage;

      decodedMessage = decodeCHATONLINELIST(message);
      if (decodedMessage instanceof CHATONLINELIST) return decodedMessage;

      decodedMessage = decodeCHATUSERLIST(message);
      if (decodedMessage instanceof CHATUSERLIST) return decodedMessage;

      decodedMessage = decodeROOMLIST(message);
      if (decodedMessage instanceof ROOMLIST) return decodedMessage;

      decodedMessage = decodeENTERROOM(message);
      if (decodedMessage instanceof ENTERROOM) return decodedMessage;

      decodedMessage = decodeLEAVEROOM(message);
      if (decodedMessage instanceof LEAVEROOM) return decodedMessage;

      decodedMessage = decodeLEAVEPRIVATECHAT(message);
      if (decodedMessage instanceof LEAVEPRIVATECHAT) return decodedMessage;

      decodedMessage = decodeHISTORYMESSAGE(message);
      if (decodedMessage instanceof HISTORYMESSAGE) return decodedMessage;

      decodedMessage = decodeCALLPRIVATECHAT(message);
      if (decodedMessage instanceof CALLPRIVATECHAT) return decodedMessage;

      decodedMessage = decodeCALLREMOTEUSER(message);
      if (decodedMessage instanceof CALLREMOTEUSER) return decodedMessage;

      decodedMessage = decodeUSERONLINELIST(message);
      if (decodedMessage instanceof USERONLINELIST) return decodedMessage;

      decodedMessage = decodeTRANSFER(message);
      if (decodedMessage instanceof TRANSFER) return decodedMessage;

      decodedMessage = decodeFTSDOWNLOAD(message);
      if (decodedMessage instanceof FTSDOWNLOAD) return decodedMessage;

      decodedMessage = decodeCREATETEMPROOM(message);
      if (decodedMessage instanceof CREATETEMPROOM) return decodedMessage;

      decodedMessage = decodeUSRLOGIN(message);
      if (decodedMessage instanceof USRLOGIN) return decodedMessage;

      decodedMessage = decodeUPDATEUSER(message);
      if (decodedMessage instanceof UPDATEUSER) return decodedMessage;

      decodedMessage = decodeSIGNIN(message);
      if (decodedMessage instanceof SIGNIN) return decodedMessage;

      decodedMessage = decodeDELETEUSER(message);
      if (decodedMessage instanceof DELETEUSER) return decodedMessage;

      decodedMessage = decodeREADTOPICROOMOWNER(message);
      if (decodedMessage instanceof READTOPICROOMOWNER) return decodedMessage;

      decodedMessage = decodeTOPICMEMBER(message);
      if (decodedMessage instanceof TOPICMEMBER) return decodedMessage;

      decodedMessage = decodeCANDIDATETOPICMEMBER(message);
      if (decodedMessage instanceof CANDIDATETOPICMEMBER) return decodedMessage;

      decodedMessage = decodeCHANGETOPICMEMBER(message);
      if (decodedMessage instanceof CHANGETOPICMEMBER) return decodedMessage;

      decodedMessage = decodeDELETEROOM(message);
      if (decodedMessage instanceof DELETEROOM) return decodedMessage;

      decodedMessage = decodePRIVATECHATFILE(message);
      if (decodedMessage instanceof PRIVATECHATFILE) return decodedMessage;
    }
    catch (UnsupportedEncodingException e) {
      throw new DecodeException(message, e.getMessage());
    }
    throw new DecodeException(
        message, message + " - Die Botschaft entspricht nicht dem vereinbarten Protokoll."
    );
  }



  public MESSAGE decodeNEWMOUSEPOINTER(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.NEWMOUSEPOINTER.name().equals(command)) return new MESSAGE();
    NEWMOUSEPOINTER mousepointer = new NEWMOUSEPOINTER();
    mousepointer.setCommand(Command.NEWMOUSEPOINTER);
    mousepointer.setHeader(header);
    mousepointer.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case CONFIRM:
        break;
      case ERROR:
        break;
      case REQUEST:
        try {
          mousepointer.setX(attr.getAsJsonPrimitive(NEWMOUSEPOINTER.X).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "Protokollfehler: NEWMOUSEPOINTER | REQUEST, das Attribut X wurde nicht definiert."
          );
        }
        try {
          mousepointer.setY(attr.getAsJsonPrimitive(NEWMOUSEPOINTER.Y).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "Protokollfehler: NEWMOUSEPOINTER | REQUEST, das Attribut Y wurde nicht definiert."
          );
        }
        break;
      case RESPONSE:
        break;
      default:
        break;
    }
    return mousepointer;
  }



  public MESSAGE decodeNEWIMAGE(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.NEWIMAGE.name().equals(command)) return new MESSAGE();
    NEWIMAGE newimage = new NEWIMAGE();
    newimage.setCommand(Command.NEWIMAGE);
    newimage.setHeader(header);
    newimage.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case CONFIRM:
        break;
      case ERROR:
        break;
      case REQUEST:
        try {
          newimage.setPseudoid(attr.getAsJsonPrimitive(NEWIMAGE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: NEWIMAGE | REQUEST, das Attribut PSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: NEWIMAGE | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        break;
      case RESPONSE:
        break;
      default:
        break;
    }
    return newimage;
  }



  public MESSAGE decodeSTOPSENDINGVIDEO(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.STOPSENDINGVIDEO.name().equals(command)) return new MESSAGE();
    STOPSENDINGVIDEO stopSendingVideo = new STOPSENDINGVIDEO();
    stopSendingVideo.setCommand(Command.STOPSENDINGVIDEO);
    stopSendingVideo.setHeader(header);
    stopSendingVideo.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case CONFIRM:
        break;
      case ERROR:
        break;
      case REQUEST:
        try {
          stopSendingVideo.setUserid(attr.getAsJsonPrimitive(STOPSENDINGVIDEO.USERID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut USERID wurde nicht definiert.");
        }
        break;
      case RESPONSE:
        break;
      default:
        break;

    }
    return stopSendingVideo;
  }



  private MESSAGE decodeCONFERENCEMUTE(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.CONFERENCEMUTE.name().equals(command)) return new MESSAGE();
    CONFERENCEMUTE mute = new CONFERENCEMUTE();
    mute.setCommand(Command.CONFERENCEMUTE);
    mute.setHeader(header);
    mute.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case CONFIRM:
        break;
      case ERROR:
        break;
      case REQUEST:
        try {
          mute.setKonferenzraum(attr.getAsJsonPrimitive(CONFERENCEMUTE.KONFERENZRAUM).getAsString());
        }
        catch (NullPointerException e) {
          // optional
          log.fatal(
              "Protokollfehler: CONFERENCEMUTE | REQUEST, das Attribut KONFERENZRAUM wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCEMUTE | REQUEST, das Attribut KONFERENZRAUM wurde nicht definiert."
          );
        }
        try {
          mute.setPseudoid(attr.getAsJsonPrimitive(CONFERENCEMUTE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        try {
          mute.setMute(attr.getAsJsonPrimitive(CONFERENCEMUTE.MUTE).getAsBoolean());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CONFERENCEMUTE | REQUEST, das Attribut MUTE wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: CONFERENCEMUTE | REQUEST, das Attribut MUTE wurde nicht definiert."
          );
        }

        try {
          mute.setConferencekey(attr.getAsJsonPrimitive(CONFERENCEMUTE.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CONFERENCEMUTE | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCEMUTE | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
          );
        }

        break;
      case RESPONSE:
        break;
      default:
        break;
    }

    return mute;

  }



  private MESSAGE decodeCONFERENCEVIDEO(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.CONFERENCEVIDEO.name().equals(command)) return new MESSAGE();
    CONFERENCEVIDEO conferenceVideo = new CONFERENCEVIDEO();
    conferenceVideo.setCommand(Command.CONFERENCEVIDEO);
    conferenceVideo.setHeader(header);
    conferenceVideo.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case CONFIRM:
        break;
      case ERROR:
        try {
          conferenceVideo.setShared(attr.getAsJsonPrimitive(CONFERENCEVIDEO.SHARING).getAsBoolean());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut SHARING wurde nicht definiert.");
        }
        try {
          conferenceVideo.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {} // optional
        break;
      case REQUEST:
        try {
          conferenceVideo.setNickname(attr.getAsJsonPrimitive(CONFERENCEVIDEO.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut NICKNAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut NICKNAME wurde nicht definiert."
          );
        }
        try {
          conferenceVideo
              .setKonferenzraum(attr.getAsJsonPrimitive(CONFERENCEVIDEO.KONFERENZRAUM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut KONFERENZRAUM wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut KONFERENZRAUM wurde nicht definiert."
          );
        }
        try {
          conferenceVideo.setShared(attr.getAsJsonPrimitive(CONFERENCEVIDEO.SHARING).getAsBoolean());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut SHARING wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut SHARING wurde nicht definiert."
          );
        }

        try {
          conferenceVideo
              .setConferencekey(attr.getAsJsonPrimitive(CONFERENCEVIDEO.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
//          log.fatal(
//              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
//          );
//          throw new DecodeException(
//              message,
//              "Protokollfehler: CONFERENCEVIDEO | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
//          );
        }

        break;
      case RESPONSE:
        break;
      default:
        break;
    }

    return conferenceVideo;

  }



  public MESSAGE decodeBEAMEROFF(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.BEAMEROFF.name().equals(command)) return new MESSAGE();
    BEAMEROFF beamer = new BEAMEROFF();
    beamer.setCommand(Command.BEAMEROFF);
    beamer.setHeader(header);
    beamer.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);

    switch(header) {
      case REQUEST:
        try {
          beamer.setPseudoid(attr.getAsJsonPrimitive(BEAMEROFF.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: BEAMEROFF | REQUEST, das Attribut PSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: BEAMEROFF | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        break;
      case RESPONSE:
        try {
          beamer.setPseudoid(attr.getAsJsonPrimitive(BEAMEROFF.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: BEAMEROFF | RESPONSE, das Attribut PSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: BEAMEROFF | RESPONSE, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        break;
    }
    return beamer;
  }



  public MESSAGE decodeBREAKROOMS(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.BREAKROOMS.name().equals(command)) return new MESSAGE();
    BREAKROOMS breakrooms = new BREAKROOMS();
    breakrooms.setCommand(Command.BREAKROOMS);
    breakrooms.setHeader(header);
    if (REQUEST.equals(header)) {
      breakrooms.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        breakrooms.setUserid(attr.get(BREAKROOMS.USERID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut USERID wurde nicht definiert.");
      }
    }
    else if (RESPONSE.equals(header)) {
      breakrooms.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        breakrooms.setUserid(attr.get(BREAKROOMS.USERID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut USERID wurde nicht definiert.");
      }
      try {
        JsonArray jsonarray = attr.getAsJsonArray(BREAKROOMS.ROOMS);
        String[] rooms = new String[jsonarray.size()];
        for (int index = 0; index < rooms.length; index++) {
          rooms[index] = jsonarray.get(index).getAsString();
        }
        breakrooms.setRooms(rooms);
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut ROOMS wurde nicht definiert.");
      }
    }
    return breakrooms;
  }



  MESSAGE decodeCALLPRIVATECHAT(String message) throws DecodeException {
    CALLPRIVATECHAT call = new CALLPRIVATECHAT();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CALLPRIVATECHAT.name().equals(command)) {
      if (REQUEST == header) {
        call.setCommand(Command.CALLPRIVATECHAT);
        call.setHeader(REQUEST);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setPseudoid(attr.getAsJsonPrimitive(CALLPRIVATECHAT.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CALLPRIVATECHAT | REQUEST, das Attribut LOCAL_PSEUDOID wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CALLPRIVATECHAT | REQUEST, das Attribut LOCAL_PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.LOCAL_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CALLPRIVATECHAT | REQUEST, das Attribut LOCAL_NICKNAME wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CALLPRIVATECHAT | REQUEST, das Attribut LOCAL_NICKNAME wurde nicht gesetzt."
          );
        }
        try {
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.REMOTE_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CALLPRIVATECHAT | REQUEST, das Attribut REMOTE_NICKNAME wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CALLPRIVATECHAT | REQUEST, das Attribut REMOTE_NICKNAME wurde nicht gesetzt."
          );
        }
        return call;
      }
      else if (CONFIRM == header) {
        call.setCommand(Command.CALLPRIVATECHAT);
        call.setHeader(CONFIRM);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");

        try {
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.REMOTE_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("CALLPRIVATECHAT | CONFIRM, das Attribut REMOTE_NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(
              message, "CALLPRIVATECHAT | CONFIRM, das Attribut REMOTE_NICKNAME wurde nicht gesetzt."
          );
        }
        try {
          call.setRemotePseudoid(attr.getAsJsonPrimitive(CALLPRIVATECHAT.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("CALLPRIVATECHAT | CONFIRM, das Attribut REMOTE_SESSIONID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "CALLPRIVATECHAT | CONFIRM, das Attribut REMOTE_SESSIONID wurde nicht gesetzt."
          );
        }
        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.LOCAL_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        try {
          call.setPseudoid(attr.getAsJsonPrimitive(CALLPRIVATECHAT.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        return call;
      }
      else if (RESPONSE == header) {
        call.setCommand(Command.CALLPRIVATECHAT);
        call.setHeader(RESPONSE);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.LOCAL_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("CALLPRIVATECHAT | RESPONSE, das Attribut LOCAL_NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(
              message, "CALLPRIVATECHAT | RESPONSE, das Attribut LOCAL_NICKNAME wurde nicht gesetzt."
          );
        }
        try {
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.REMOTE_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("CALLPRIVATECHAT | RESPONSE, das Attribut REMOTE_NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(
              message, "CALLPRIVATECHAT | RESPONSE, das Attribut REMOTE_NICKNAME wurde nicht gesetzt."
          );
        }
        try {
          call.setPseudoid(attr.getAsJsonPrimitive(CALLPRIVATECHAT.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("CALLPRIVATECHAT | RESPONSE, das Attribut LOCAL_SESSIONID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "CALLPRIVATECHAT | RESPONSE, das Attribut LOCAL_SESSIONID wurde nicht gesetzt."
          );
        }

        try {
          call.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        try {
          call.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {// optional
        }
        return call;
      }
      else if (ERROR == header) {
        call.setCommand(Command.CALLPRIVATECHAT);
        call.setHeader(ERROR);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");

        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.LOCAL_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLPRIVATECHAT.REMOTE_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          call.setPseudoid(attr.getAsJsonPrimitive(CALLPRIVATECHAT.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          call.setRemotePseudoid(attr.getAsJsonPrimitive(CALLPRIVATECHAT.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          // Optional
          call.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          call.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        try {
          call.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {// optional
        }

        return call;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeCALLREMOTEUSER(String message) throws DecodeException {
    CALLREMOTEUSER call = new CALLREMOTEUSER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CALLREMOTEUSER.name().equals(command)) {
      if (REQUEST == header) {
        call.setCommand(Command.CALLREMOTEUSER);
        call.setHeader(REQUEST);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLREMOTEUSER.LOCAL_NICKNAME).getAsString());
          call.setPseudoid(attr.getAsJsonPrimitive(CALLREMOTEUSER.PSEUDOID).getAsString());
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLREMOTEUSER.REMOTE_NICKNAME).getAsString());
          call.setRemotePseudoid(attr.getAsJsonPrimitive(CALLREMOTEUSER.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CALLREMOTEUSER-REQUEST, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return call;
      }
      else if (CONFIRM == header) {
        call.setCommand(Command.CALLREMOTEUSER);
        call.setHeader(CONFIRM);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLREMOTEUSER.LOCAL_NICKNAME).getAsString());
          call.setPseudoid(attr.getAsJsonPrimitive(CALLREMOTEUSER.PSEUDOID).getAsString());
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLREMOTEUSER.REMOTE_NICKNAME).getAsString());
          call.setRemotePseudoid(attr.getAsJsonPrimitive(CALLREMOTEUSER.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CALLREMOTEUSER-CONFIRM, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return call;
      }
      else if (RESPONSE == header) {
        call.setCommand(Command.CALLREMOTEUSER);
        call.setHeader(RESPONSE);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setLocalNickname(attr.getAsJsonPrimitive(CALLREMOTEUSER.LOCAL_NICKNAME).getAsString());
          call.setPseudoid(attr.getAsJsonPrimitive(CALLREMOTEUSER.PSEUDOID).getAsString());
          call.setRemoteNickname(attr.getAsJsonPrimitive(CALLREMOTEUSER.REMOTE_NICKNAME).getAsString());
          call.setRemotePseudoid(attr.getAsJsonPrimitive(CALLREMOTEUSER.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CALLREMOTEUSER-RESPONSE, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return call;
      }
      else if (ERROR == header) {
        call.setCommand(Command.CALLREMOTEUSER);
        call.setHeader(ERROR);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(CALLREMOTEUSER.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CALLREMOTEUSER | ERROR, das Attribut MULTILINGUALKEY wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CALLREMOTEUSER | ERROR, das Attribut MULTILINGUALKEY wurde nicht gesetzt."
          );
        }
        try {
          call.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CALLREMOTEUSER | ERROR, das Attribut ERRORMESSAGE wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CALLREMOTEUSER | ERROR, das Attribut ERRORMESSAGE wurde nicht gesetzt."
          );
        }
        return call;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeCANDIDATETOPICMEMBER(String message) throws DecodeException {
    CANDIDATETOPICMEMBER member = new CANDIDATETOPICMEMBER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonObject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonObject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonObject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CANDIDATETOPICMEMBER.name().equals(command)) {
      member.setCommand(Command.CANDIDATETOPICMEMBER);
      if (REQUEST == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOM wurde nicht definiert.");
        }
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut PSEUDOID wurde nicht definiert.");
        }
        return member;
      }
      else if (RESPONSE == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE, das Attribut ROOM wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE, das Attribut ROOM wurde nicht definiert."
          );
        }
        try {
          member.setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(MEMBER.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE, das Attribut ROOMTYPE wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE, das Attribut ROOMTYPE wurde nicht definiert."
          );
        }
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE, das Attribut USERID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE, das Attribut USERID wurde nicht definiert."
          );
        }
        // rooms decodieren
        JsonArray jsonarray = attr.getAsJsonArray(MEMBER.TOPICMEMBER);
        ChatUser singlemember[] = new ChatUser[jsonarray.size()];
        for (int index = 0; index < singlemember.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          singlemember[index] = new ChatUser();
          try {
            singlemember[index].setPseudoid(objectroom.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // optional
          }
          try {
            singlemember[index].setNickname(objectroom.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE | TOPICMEMEMBER, das Attribut NICKNAME wurde nicht definiert."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: CANDIDATETOPICMEMBER | RESPONSE | TOPICMEMEMBER, das Attribut NICKNAME wurde nicht definiert."
            );
          }
        }
        member.setChatUser(singlemember);
        return member;
      }
    }
    return new MESSAGE();

  }



  MESSAGE decodeCHANGETOPICMEMBER(String message) throws DecodeException {
    CHANGETOPICMEMBER member = new CHANGETOPICMEMBER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CHANGETOPICMEMBER.name().equals(command)) {
      member.setCommand(Command.CHANGETOPICMEMBER);
      if (REQUEST == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOM wurde nicht definiert.");
        }
        try {
          member.setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(MEMBER.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOMTYPE wurde nicht definiert.");
        }
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
          log.fatal(
              "Protokollfehler: CHANGETOPICMEMBER | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message,
              "Protokollfehler: CHANGETOPICMEMBER | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
          );
        }

        // rooms decodieren
        JsonArray jsonarray = null;
        try {
          jsonarray = attr.getAsJsonArray(MEMBER.TOPICMEMBER).getAsJsonArray();
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut TOPICMEMBER wurde nicht definiert.");
        }
        ChatUser singlemember[] = new ChatUser[jsonarray.size()];
        for (int index = 0; index < singlemember.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          singlemember[index] = new ChatUser();
          try {
            singlemember[index].setPseudoid(objectroom.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // optional
          }
          try {
            singlemember[index].setNickname(objectroom.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            throw new DecodeException(message, "Das Attribut TOPICMEMBER.NICKNAME wurde nicht definiert.");
          }
        }
        member.setChatUser(singlemember);
        return member;
      }
      else if (RESPONSE == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut ROOM wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut ROOM wurde nicht definiert."
          );
        }
        try {
          member.setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(MEMBER.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut ROOMTYPE wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut ROOMTYPE wurde nicht definiert."
          );
        }
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut PSEUDOID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        // rooms decodieren
        JsonArray jsonarray = attr.getAsJsonArray(MEMBER.TOPICMEMBER);
        ChatUser singlemember[] = new ChatUser[jsonarray.size()];
        for (int index = 0; index < singlemember.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          singlemember[index] = new ChatUser();
          try {
            singlemember[index].setPseudoid(objectroom.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // optional
          }
          try {
            singlemember[index].setNickname(objectroom.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut NICKNAME wurde nicht definiert."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: CHANGETOPICMEMBER | RESPONSE, das Attribut NICKNAME wurde nicht definiert."
            );
          }
        }
        member.setChatUser(singlemember);
        return member;
      }
      else if (ERROR == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CHANGETOPICMEMBER | ERROR, das Attribut PSEUDOID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CHANGETOPICMEMBER | ERROR, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {}

        try {
          member.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CHANGETOPICMEMBER | ERROR, das Attribut ERRORMESSAGE wurde nicht definiert."
          );
          throw new DecodeException(message, "Das Attribut ERRORMESSAGE wurde nicht definiert.");
        }
        return member;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeCHATMESSAGE(String message) throws DecodeException {
    CHATMESSAGE usermessage = new CHATMESSAGE();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CHATMESSAGE.name().equals(command)) {
      usermessage.setCommand(Command.CHATMESSAGE);
      if (REQUEST == header) {
        usermessage.setHeader(header);
        usermessage.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        usermessage.setRoom(attr.getAsJsonPrimitive(CHATMESSAGE.ROOM).getAsString());
        try {
          String text = attr.getAsJsonPrimitive(CHATMESSAGE.MESSAGE).getAsString();
          usermessage.setMessage(text);
          JsonObject userobject = attr.getAsJsonObject(CHATMESSAGE.CHATUSER);
          ChatUser chatuser = new ChatUser();
          chatuser.setBackgroundColor(userobject.getAsJsonPrimitive(ChatUser.BACKGROUND_COLOR).getAsInt());
          chatuser.setForegroundColor(userobject.getAsJsonPrimitive(ChatUser.FOREGROUND_COLOR).getAsInt());
          chatuser.setNickname(userobject.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          chatuser.setPseudoid(userobject.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          usermessage.setChatUser(chatuser);
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CHATMESSAGE-REQUEST, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        try {
          // optional
          usermessage.setAttachment(attr.getAsJsonPrimitive(Attachment.ATTACHMENT).getAsLong());
          try {
            usermessage.setFilename(attr.getAsJsonPrimitive(Attachment.FILENAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: CHATMESSAGE | REQUEST | FILENAME, das Attribut FILENAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: CHATMESSAGE | REQUEST | FILENAME, das Attribut FILENAME wurde nicht gesetzt."
            );
          }
          try {
            usermessage.setFilesize(attr.getAsJsonPrimitive(Attachment.FILESIZE).getAsLong());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: CHATMESSAGE | REQUEST | FILENAME, das Attribut FILESIZE wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: CHATMESSAGE | REQUEST | FILENAME, das Attribut FILESIZE wurde nicht gesetzt."
            );
          }

        }
        catch (NullPointerException e) {}

        return usermessage;
      }
      else if (RESPONSE == header) {
        usermessage.setHeader(header);
        usermessage.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        String room = attr.getAsJsonPrimitive(CHATMESSAGE.ROOM).getAsString();
        usermessage.setRoom(room);
        try {
          usermessage.setDatetime(attr.getAsJsonPrimitive(CHATMESSAGE.DATETIME).getAsLong());
        }
        catch (NullPointerException e) {}
        try {
          // optional
          usermessage.setAttachment(attr.getAsJsonPrimitive(Attachment.ATTACHMENT).getAsLong());
          try {
            usermessage.setFilename(attr.getAsJsonPrimitive(Attachment.FILENAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: CHATMESSAGE | RESPONSE | FILENAME, das Attribut FILENAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: CHATMESSAGE | RESPONSE | FILENAME, das Attribut FILENAME wurde nicht gesetzt."
            );
          }
          try {
            usermessage.setFilesize(attr.getAsJsonPrimitive(Attachment.FILESIZE).getAsLong());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: CHATMESSAGE | RESPONSE | FILESIZE, das Attribut FILENAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: CHATMESSAGE | RESPONSE | FILESIZE, das Attribut FILENAME wurde nicht gesetzt."
            );
          }

        }
        catch (NullPointerException e) {}

        try {
          String text = attr.getAsJsonPrimitive(CHATMESSAGE.MESSAGE).getAsString();
          usermessage.setMessage(text);
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CHATMESSAGE | RESPONSE, das Attribut MESSAGE wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: CHATMESSAGE | RESPONSEE, das Attribut MESSAGE wurde nicht gesetzt."
          );
        }

        try {
          JsonObject userobject = attr.getAsJsonObject(CHATMESSAGE.CHATUSER);
          ChatUser chatuser = new ChatUser();
          chatuser.setBackgroundColor(userobject.getAsJsonPrimitive(ChatUser.BACKGROUND_COLOR).getAsInt());
          chatuser.setForegroundColor(userobject.getAsJsonPrimitive(ChatUser.FOREGROUND_COLOR).getAsInt());
          chatuser.setNickname(userobject.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());

          try {
            chatuser.setPseudoid(userobject.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // optional
          }

          usermessage.setChatUser(chatuser);
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CHATMESSAGE-RESPONSE, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }

        return usermessage;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeCHATONLINELIST(String message) throws DecodeException {
    CHATONLINELIST chatonlinelist = new CHATONLINELIST();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CHATONLINELIST.name().equals(command)) {
      chatonlinelist.setCommand(Command.CHATONLINELIST);
      if (REQUEST == header) {
        chatonlinelist.setHeader(header);
        chatonlinelist.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        JsonArray jsonarray = attr.getAsJsonArray(CHATONLINELIST.CHATONLINELIST);
        ChatOnline online[] = new ChatOnline[jsonarray.size()];
        for (int index = 0; index < online.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          online[index] = new ChatOnline();
          online[index].setOnline(objectroom.getAsJsonPrimitive(ChatOnline.ONLINE).getAsInt());
          online[index].setRoom(objectroom.getAsJsonPrimitive(ChatOnline.ROOM).getAsString());
        }
        chatonlinelist.setChatOnline(online);
        return chatonlinelist;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeCHATUSERLIST(String message) throws DecodeException {
    CHATUSERLIST userlist = new CHATUSERLIST();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CHATUSERLIST.name().equals(command)) {
      userlist.setCommand(Command.CHATUSERLIST);
      if (RESPONSE == header) {
        userlist.setHeader(header);
        userlist.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");

        String room = attr.getAsJsonPrimitive(CHATUSERLIST.ROOM).getAsString();
        userlist.setRoom(room);

        JsonArray jsonarray = attr.getAsJsonArray(CHATUSERLIST.CHATUSER);
        ChatUser chatuser[] = new ChatUser[jsonarray.size()];
        for (int index = 0; index < chatuser.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          chatuser[index] = new ChatUser();
          chatuser[index]
              .setBackgroundColor(objectroom.getAsJsonPrimitive(ChatUser.BACKGROUND_COLOR).getAsInt());
          chatuser[index]
              .setForegroundColor(objectroom.getAsJsonPrimitive(ChatUser.FOREGROUND_COLOR).getAsInt());
          chatuser[index].setNickname(objectroom.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          try {
            // optional
            chatuser[index].setPseudoid(objectroom.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {}
        }
        userlist.setChatUser(chatuser);
        return userlist;
      }
      else if (REQUEST == header) {
        userlist.setHeader(header);
        userlist.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        userlist.setRoom(attr.getAsJsonPrimitive(CHATUSERLIST.ROOM).getAsString());
        return userlist;
      }
      else if (ERROR == header) {
        userlist.setHeader(header);
        try {
          JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
          userlist.setErrorCode(attr.getAsJsonPrimitive(MESSAGE.ERRORCODE).getAsInt());
          userlist.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          // DATASET ist optinal
        }
        return userlist;
      }

    }
    return new MESSAGE();

  }



  public MESSAGE decodeCONFERENCE(String message)
      throws DecodeException, JsonSyntaxException, UnsupportedEncodingException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();

    HEADER header = HEADER.valueOf(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.CONFERENCE.name().equals(command)) return new MESSAGE();
    CONFERENCE conference = new CONFERENCE();
    conference.setCommand(Command.CONFERENCE);
    conference.setHeader(header);
    conference.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);

    switch(header) {
      case CONFIRM:
        break;
      case ERROR:
        break;
      case REQUEST:
        try {
          conference.setKonferenzraum(attr.getAsJsonPrimitive(CONFERENCE.KONFERENZRAUM).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCE | REQUEST, das Attribut KONFERENZNAME wurde nicht definiert."
          );
        }
        try {
          conference.setConferenceKey(attr.getAsJsonPrimitive(CONFERENCE.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        try {
          conference.setPseudoid(attr.getAsJsonPrimitive(CONFERENCE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "Protokollfehler: CONFERENCE | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          conference.setSession(attr.getAsJsonPrimitive(CONFERENCE.SESSION).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "Protokollfehler: CONFERENCE | REQUEST, das Attribut SESSION wurde nicht definiert."
          );
        }
        conference.setOffhook(attr.getAsJsonPrimitive(CONFERENCE.OFFHOOK).getAsBoolean());
        break;
      case RESPONSE:
        try {
          conference.setKonferenzraum(attr.getAsJsonPrimitive(CONFERENCE.KONFERENZRAUM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CONFERENCE | RESPONSE, das Attribut KONFERENZNAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCE | RESPONSE, das Attribut KONFERENZNAME wurde nicht definiert."
          );
        }
        try {
          conference.setConferenceKey(attr.getAsJsonPrimitive(CONFERENCE.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        try {
          conference.setPseudoid(attr.getAsJsonPrimitive(CONFERENCE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CONFERENCE | RESPONSE, das Attribut USERID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: CONFERENCE | RESPONSE, das Attribut USERID wurde nicht definiert."
          );
        }
        try {
          conference.setOffhook(attr.getAsJsonPrimitive(CONFERENCE.OFFHOOK).getAsBoolean());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CONFERENCE | RESPONSE, das Attribut OFFHOOK wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: CONFERENCE | RESPONSE, das Attribut OFFHOOK wurde nicht definiert."
          );
        }
        JsonArray konferenzraumArray = attr.getAsJsonArray(CONFERENCE.KONFERENZRAUMUSER);
        int count = konferenzraumArray.size();
        KonferenzraumUser[] konfernzraumuser = new KonferenzraumUser[count];
        for (int index = 0; index < count; index++) {
          konfernzraumuser[index] = new KonferenzraumUser();
          JsonObject konferenzraum = konferenzraumArray.get(index).getAsJsonObject();
          konfernzraumuser[index]
              .setAnwesend(konferenzraum.getAsJsonPrimitive(KonferenzraumUser.ANWESEND).getAsBoolean());

          try {
            konfernzraumuser[index].setWebsocketSession(
                konferenzraum.getAsJsonPrimitive(KonferenzraumUser.SESSION).getAsString()
            );
          }
          catch (NullPointerException e) {}
          try {
            konfernzraumuser[index]
                .setMute(konferenzraum.getAsJsonPrimitive(KonferenzraumUser.MUTE).getAsBoolean());
          }
          catch (NullPointerException e) {
            log.fatal("Protokollfehler: CONFERENCE | RESPONSE, das Attribut MUTE wurde nicht definiert.");
            throw new DecodeException(
                message, "Protokollfehler: CONFERENCE | RESPONSE, das Attribut MUTE wurde nicht definiert."
            );
          }
          JsonObject chatuser = konferenzraum.getAsJsonObject(KonferenzraumUser.CHATUSER);
          konfernzraumuser[index].setForegroundColor(chatuser.get(ChatUser.FOREGROUND_COLOR).getAsInt());
          konfernzraumuser[index].setBackgroundColor(chatuser.get(ChatUser.BACKGROUND_COLOR).getAsInt());
          konfernzraumuser[index].setNickname(chatuser.get(ChatUser.NICKNAME).getAsString());
          try {
            konfernzraumuser[index].setPseudoid(chatuser.get(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // userid ist optional, sollte aber aus Sicherheitsgründen entfernt werden
          }
        }
        conference.setKonferenzraumUser(konfernzraumuser);
        break;
      default:
        break;
    }
    return conference;
  }



  public MESSAGE decodeCONFERENCEAUDIO(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();

    HEADER header = HEADER.valueOf(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.CONFERENCEAUDIO.name().equals(command)) return new MESSAGE();

    CONFERENCEAUDIO conferenceaudio = new CONFERENCEAUDIO();
    conferenceaudio.setCommand(Command.CONFERENCEAUDIO);
    conferenceaudio.setHeader(header);
    conferenceaudio.setDataset(Protocol.DATASET);

    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);

    switch(header) {
      case REQUEST:
        try {
          conferenceaudio.setWebsocketSession(attr.getAsJsonPrimitive(CONFERENCEAUDIO.SOURCE).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CONFERENCEAUDIO | REQUEST, das Attribut SOURCE wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: CONFERENCEAUDIO | REQUEST, das Attribut SOURCE wurde nicht gesetzt."
          );
        }
        try {
          conferenceaudio
              .setConferencekey(attr.getAsJsonPrimitive(CONFERENCEAUDIO.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: CONFERENCEAUDIO | REQUEST, das Attribut CONFERENCEKEY wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: CONFERENCEAUDIO | REQUEST, das Attribut CONFERENCEKEY wurde nicht gesetzt."
          );
        }

        // STREAM_ID
        try {
          conferenceaudio.setStreamId(attr.getAsJsonPrimitive(CONFERENCEAUDIO.STREAM_ID).getAsString());
        }
        catch (NullPointerException e) {}

        break;
      case CONFIRM:
      case ERROR:
      case RESPONSE:
      default:
        break;
    }

    return conferenceaudio;
  }



  MESSAGE decodeCREATETEMPROOM(String message) throws DecodeException {
    CREATETEMPROOM temproom = new CREATETEMPROOM();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.CREATETEMPROOM.name().equals(command)) {
      if (REQUEST == header) {
        temproom.setCommand(Command.CREATETEMPROOM);
        temproom.setHeader(REQUEST);
        temproom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          temproom.setRoom(attr.getAsJsonPrimitive(CREATETEMPROOM.ROOM).getAsString());
          temproom.setPseudoid(attr.getAsJsonPrimitive(CREATETEMPROOM.PSEUDOID).getAsString());
          temproom.setEntry(Entry.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.ENTRY).getAsString()));
          temproom
              .setLifetime(Lifetime.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.LIFETIME).getAsString()));
          temproom.setNickname(attr.getAsJsonPrimitive(CREATETEMPROOM.NICKNAME).getAsString());
          temproom
              .setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CREATETEMPROOM-REQUEST, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return temproom;
      }
      else if (RESPONSE == header) {
        temproom.setCommand(Command.CREATETEMPROOM);
        temproom.setHeader(RESPONSE);
        temproom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          temproom.setRoom(attr.getAsJsonPrimitive(CREATETEMPROOM.ROOM).getAsString());
          temproom.setPseudoid(attr.getAsJsonPrimitive(CREATETEMPROOM.PSEUDOID).getAsString());
          temproom.setEntry(Entry.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.ENTRY).getAsString()));
          temproom
              .setLifetime(Lifetime.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.LIFETIME).getAsString()));
          temproom
              .setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.ROOMTYPE).getAsString()));
          try {
            temproom.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
          }
          catch (NullPointerException e) {
            // ist optional
          }
          try {
            temproom.setMultilingualkey(
                KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
            );
          }
          catch (NullPointerException e) {
            // ist optional
          }
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "CREATETEMPROOM-RESPONSE, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return temproom;
      }
      else if (ERROR == header) {
        temproom.setCommand(Command.CREATETEMPROOM);
        temproom.setHeader(ERROR);
        temproom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          temproom.setPseudoid(attr.getAsJsonPrimitive(CREATETEMPROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CREATETEMPROOM | ERROR, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: CREATETEMPROOM | ERROR, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          temproom.setRoom(attr.getAsJsonPrimitive(CREATETEMPROOM.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: CREATETEMPROOM | ERROR, das Attribut ROOM wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: CREATETEMPROOM | ERROR, das Attribut ROOM wurde nicht gesetzt."
          );
        }
        try {
          // optional
          temproom.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          // optional
          temproom.setErrorCode(attr.getAsJsonPrimitive(MESSAGE.ERRORCODE).getAsInt());
        }
        catch (NullPointerException e) {}
        try {
          temproom
              .setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "CREATETEMPROOM, das Attribut ROOMTYPE wurde nicht gesetzt.");
        }
        try {
          // optional
          temproom.setEntry(Entry.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.ENTRY).getAsString()));
        }
        catch (NullPointerException e) {}
        try {
          // optional
          temproom
              .setLifetime(Lifetime.valueOf(attr.getAsJsonPrimitive(CREATETEMPROOM.LIFETIME).getAsString()));
        }
        catch (NullPointerException e) {}
        try {
          // optional
          temproom.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          temproom.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {
          // ist optional
        }

        return temproom;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeDELETEROOM(String message) throws DecodeException {
    DELETEROOM delete = new DELETEROOM();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.DELETEROOM.name().equals(command)) {
      delete.setCommand(Command.DELETEROOM);
      if (REQUEST == header) {
        delete.setHeader(header);
        delete.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        try {
          delete.setPseudoid(attr.getAsJsonPrimitive(DELETEROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: REQUEST | DELETEROOM, das Attribut PSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: REQUEST | DELETEROOM, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          delete.setRoom(attr.getAsJsonPrimitive(DELETEROOM.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: REQUEST | DELETEROOM, das Attribut ROOM wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: REQUEST | DELETEROOM, das Attribut ROOM wurde nicht definiert."
          );
        }
        return delete;
      }
      else if (RESPONSE == header) {
        delete.setHeader(header);
        delete.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        try {
          delete.setPseudoid(attr.getAsJsonPrimitive(DELETEROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: RESPONSE | DELETEROOM, das Attribut PSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: RESPONSE | DELETEROOM, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          delete.setRoom(attr.getAsJsonPrimitive(DELETEROOM.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: RESPONSE | DELETEROOM, das Attribut ROOM wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: RESPONSE | DELETEROOM, das Attribut ROOM wurde nicht definiert."
          );
        }
        try {
          delete.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {}
        return delete;
      }
      else if (ERROR == header) {
        delete.setHeader(header);
        delete.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        try {
          delete.setPseudoid(attr.getAsJsonPrimitive(DELETEROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: ERROR | DELETEROOM, das Attribut PSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: ERROR | DELETEROOM, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          delete.setRoom(attr.getAsJsonPrimitive(DELETEROOM.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: ERROR | DELETEROOM, das Attribut ROOM wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: ERROR | DELETEROOM, das Attribut ROOM wurde nicht definiert."
          );
        }
        try {
          delete.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: ERROR | DELETEROOM, das Attribut TEXT wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: ERROR | DELETEROOM, das Attribut TEXT wurde nicht definiert."
          );
        }
        return delete;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeDELETEUPLOADFILES(String message) throws DecodeException {
    DELETEUPLOADFILES deletefiles = new DELETEUPLOADFILES();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.DELETEUPLOADFILES.name().equals(command)) {
      deletefiles.setCommand(Command.DELETEUPLOADFILES);
      if (REQUEST == header) {
        deletefiles.setHeader(REQUEST);
        deletefiles.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          deletefiles.setPseudoid(attr.getAsJsonPrimitive(DELETEUPLOADFILES.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | DELETEUPLOADFILES, das Attribut PSEUDOID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | DELETEUPLOADFILES, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          deletefiles.setIp(attr.getAsJsonPrimitive(DELETEUPLOADFILES.IP).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: REQUEST | DELETEUPLOADFILES, das Attribut IP wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: REQUEST | DELETEUPLOADFILES, das Attribut IP wurde nicht definiert."
          );
        }
        return deletefiles;
      }
      else if (CONFIRM == header) {
        deletefiles.setHeader(CONFIRM);
        return deletefiles;
      }
      else if (ERROR == header) {
        deletefiles.setHeader(ERROR);
        deletefiles.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        deletefiles.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        deletefiles.setErrorCode(attr.getAsJsonPrimitive(MESSAGE.ERRORCODE).getAsInt());
        deletefiles.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        return deletefiles;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeDELETEUSER(String message) throws DecodeException {
    DELETEUSER deleteuser = new DELETEUSER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.DELETE_USER.name().equals(command)) {
      if (REQUEST == header) {
        deleteuser.setCommand(Command.DELETE_USER);
        deleteuser.setHeader(header);
        deleteuser.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        try {
          deleteuser.setUserid(attr.getAsJsonPrimitive(USER.USERID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "DELETEUSER-REQUEST, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return deleteuser;
      }
      else if (CONFIRM == header) {
        deleteuser.setCommand(Command.DELETE_USER);
        deleteuser.setHeader(header);
        return deleteuser;
      }
      else if (ERROR == header) {
        deleteuser.setCommand(Command.DELETE_USER);
        deleteuser.setHeader(header);
        return deleteuser;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeDIAL(String message) throws DecodeException {
    DIAL dial = new DIAL();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.DIAL.name().equals(command)) return new MESSAGE();
    dial.setCommand(Command.DIAL);
    dial.setHeader(header);
    if (REQUEST == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      dial.setDataset(Protocol.DATASET);
      try {
        dial.setCallerPseudoid(attr.get(DIAL.CALLER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_USERID wurde nicht definiert.");
      }
      try {
        dial.setCallerNickname(attr.get(DIAL.CALLER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut NICKNAME wurde nicht definiert.");
      }
      try {
        dial.setCallerVoice(attr.get(DIAL.CALLER_VOICE).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_VOICE wurde nicht definiert.");
      }
      try {
        dial.setReceiverIp(attr.get(DIAL.RECEIVER_IP).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        dial.setReceiverPort(attr.get(DIAL.RECEIVER_PORT).getAsInt());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        dial.setReceiverNickname(attr.get(DIAL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
      }
      try {
        dial.setReceiverPseudoid(attr.get(DIAL.RECEIVER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
    }
    else if (RESPONSE == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      dial.setDataset(Protocol.DATASET);
      try {
        dial.setCallerPseudoid(attr.get(DIAL.CALLER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_USERID wurde nicht definiert.");
      }
      try {
        dial.setCallerNickname(attr.get(DIAL.CALLER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut NICKNAME wurde nicht definiert.");
      }
      try {
        dial.setCallerVoice(attr.get(DIAL.CALLER_VOICE).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_VOICE wurde nicht definiert.");
      }
      try {
        dial.setReceiverIp(attr.get(DIAL.RECEIVER_IP).getAsString());
      }
      catch (NullPointerException e) {
        // optional
//        throw new DecodeException(message, "Das Attribut RECEIVER_IP wurde nicht definiert.");
      }
      try {
        dial.setReceiverPort(attr.get(DIAL.RECEIVER_PORT).getAsInt());
      }
      catch (NullPointerException e) {
        // optional
//        throw new DecodeException(message, "Das Attribut RECEIVER_PORT wurde nicht definiert.");
      }
      try {
        dial.setReceiverNickname(attr.get(DIAL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
      }
      try {
        dial.setReceiverPseudoid(attr.get(DIAL.RECEIVER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_USERID wurde nicht definiert.");
      }
      try {
        dial.setReceiverSession(attr.get(DIAL.RECEIVER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_SESSION wurde nicht definiert.");
      }
      try {
        dial.setCallerSession(attr.get(DIAL.CALLER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_SESSION wurde nicht definiert.");
      }

    }
    else if (ERROR == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      dial.setDataset(Protocol.DATASET);
      try {
        dial.setCallerPseudoid(attr.get(DIAL.CALLER_PSEUDOID).getAsString());
        dial.setCallerNickname(attr.get(DIAL.CALLER_NICKNAME).getAsString());
        dial.setCallerVoice(attr.get(DIAL.CALLER_VOICE).getAsString());
        dial.setReceiverIp(attr.get(DIAL.RECEIVER_IP).getAsString());
        dial.setReceiverPort(attr.get(DIAL.RECEIVER_PORT).getAsInt());
      }
      catch (NullPointerException e) {
        // optional
      }

      try {
        dial.setErrorMessage(attr.get(MESSAGE.ERRORMESSAGE).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }

      try {
        dial.setReceiverNickname(attr.get(DIAL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
      }
      try {
        dial.setMultilingualkey(
            KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
        );
      }
      catch (NullPointerException e) {
        // optional
      }
    }
    return dial;
  }



  MESSAGE decodeDOWNLOAD(String message) throws DecodeException {
    DOWNLOAD download = new DOWNLOAD();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.DOWNLOAD.name().equals(command)) {
      download.setCommand(Command.DOWNLOAD);
      if (REQUEST == header) {
        download.setHeader(REQUEST);
        download.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          download.setPseudoid(attr.getAsJsonPrimitive(DOWNLOAD.PSEUDOID).getAsString());
          download.setFilename(attr.getAsJsonPrimitive(DOWNLOAD.FILENAME).getAsString());
          download.setIndex(attr.getAsJsonPrimitive(DOWNLOAD.INDEX).getAsInt());
          download.setSlot(attr.getAsJsonPrimitive(DOWNLOAD.SLOT).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return download;
      }
      else if (RESPONSE == header) {
        download.setHeader(header);
        download.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          download.setPseudoid(attr.getAsJsonPrimitive(DOWNLOAD.PSEUDOID).getAsString());
          download.setFilename(attr.getAsJsonPrimitive(DOWNLOAD.FILENAME).getAsString());
          download.setIndex(attr.getAsJsonPrimitive(DOWNLOAD.INDEX).getAsInt());
          download.setSlot(attr.getAsJsonPrimitive(DOWNLOAD.SLOT).getAsInt());
          download.setPathfile(attr.getAsJsonPrimitive(DOWNLOAD.PATHFILE).getAsString());
          download.setIp(attr.getAsJsonPrimitive(DOWNLOAD.IP).getAsString());
          download.setPort(attr.getAsJsonPrimitive(DOWNLOAD.PORT).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return download;
      }
      else if (ERROR == header) {
        download.setHeader(header);
        download.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          download.setPseudoid(attr.getAsJsonPrimitive(DOWNLOAD.PSEUDOID).getAsString());
          download.setFilename(attr.getAsJsonPrimitive(DOWNLOAD.FILENAME).getAsString());
          download.setIndex(attr.getAsJsonPrimitive(DOWNLOAD.INDEX).getAsInt());
          download.setSlot(attr.getAsJsonPrimitive(DOWNLOAD.SLOT).getAsInt());
          download.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return download;
      }

    }
    return new MESSAGE();
  }



  MESSAGE decodeENTERROOM(String message) throws DecodeException {
    ENTERROOM enterroom = new ENTERROOM();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.ENTERROOM.name().equals(command)) {
      enterroom.setCommand(Command.ENTERROOM);
      if (REQUEST == header) {
        enterroom.setHeader(REQUEST);
        enterroom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          enterroom.setPseudoid(attr.getAsJsonPrimitive(ENTERROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("ENTERROOM | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "ENTERROOM | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          enterroom.setRoom(attr.getAsJsonPrimitive(ENTERROOM.ROOM).getAsString());
          enterroom.setNickname(attr.getAsJsonPrimitive(ENTERROOM.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "ENTERROOM-REQUEST, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return enterroom;
      }
      else if (RESPONSE == header) {
        enterroom.setHeader(RESPONSE);
        enterroom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          enterroom.setRoom(attr.getAsJsonPrimitive(ENTERROOM.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOM wurde nicht definiert.");
        }
        try {
          enterroom.setPseudoid(attr.getAsJsonPrimitive(ENTERROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("ENTERROOM | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "ENTERROOM | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          enterroom.setNickname(attr.getAsJsonPrimitive(ENTERROOM.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut NICKNAME wurde nicht definiert.");
        }
        try {
          enterroom.setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(ENTERROOM.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOMTYPE wurde nicht definiert.");
        }
        return enterroom;
      }
      else if (ERROR == header) {
        enterroom.setHeader(ERROR);
        enterroom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) {
          log.fatal("ENTERROOM | ERROR, das Attribut DATASET wurde nicht gesetzt.");
          throw new DecodeException(message, "ENTERROOM | ERROR, das Attribut DATASET wurde nicht gesetzt.");
        }

        try {
          enterroom.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(ENTERROOM.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {
          log.fatal("ENTERROOM | ERROR, das Attribut TEXT wurde nicht gesetzt.");
          throw new DecodeException(
              message, "ENTERROOM | ERROR, das Attribut MULTILINGUALKEY wurde nicht gesetzt."
          );
        }

        try {
          enterroom.setText(attr.getAsJsonPrimitive(ENTERROOM.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("ENTERROOM | ERROR, das Attribut TEXT wurde nicht gesetzt.");
          throw new DecodeException(message, "ENTERROOM | ERROR, das Attribut TEXT wurde nicht gesetzt.");
        }

        return enterroom;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeFILETYPES(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.FILETYPES.name().equals(command)) return new MESSAGE();
    FILETYPES filetypes = new FILETYPES();
    filetypes.setCommand(Command.FILETYPES);
    filetypes.setHeader(header);
    if (REQUEST == header) {
      filetypes.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        filetypes.setPseudoid(attr.get(FILETYPES.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal("Protokollfehler: FILETYPES | REQUEST, das Attribut PSEUDOID wurde nicht definiert.");
        throw new DecodeException(
            message, "Protokollfehler: FILETYPES | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
        );
      }
    }
    else if (RESPONSE == header) {
      filetypes.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        filetypes.setPseudoid(attr.get(FILETYPES.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal("Protokollfehler: FILETYPES | RESPONSE, das Attribut PSEUDOID wurde nicht definiert.");
        throw new DecodeException(message, "Das Attribut USERID wurde nicht definiert.");
      }
      JsonArray jsonarray = null;
      try {
        jsonarray = attr.getAsJsonArray(FILETYPES.FILETYPES);
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut FILETYPES wurde nicht definiert.");
      }
      BlacklistTypes blacklist[] = new BlacklistTypes[jsonarray.size()];
      for (int index = 0; index < blacklist.length; index++) {
        JsonObject objectJson = jsonarray.get(index).getAsJsonObject();
        blacklist[index] = new BlacklistTypes();
        blacklist[index].setDescription(objectJson.get(BlacklistTypes.DESCRIPTION).getAsString());
        blacklist[index].setSuffix(objectJson.get(BlacklistTypes.SUFFIX).getAsString());
        blacklist[index].setChecked(objectJson.get(BlacklistTypes.CHECKED).getAsBoolean());
      }
      filetypes.setFiletypes(blacklist);
    }
    return filetypes;
  }



  MESSAGE decodeFTSDOWNLOAD(String message) throws DecodeException {
    FTSDOWNLOAD ftsdownload = new FTSDOWNLOAD();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.FTSDOWNLOAD.name().equals(command)) {
      ftsdownload.setCommand(Command.FTSDOWNLOAD);
      if (REQUEST == header) {
        ftsdownload.setHeader(header);
        ftsdownload.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          ftsdownload.setSlot(attr.getAsJsonPrimitive(FTSDOWNLOAD.SLOT).getAsInt());
          ftsdownload.setFilename(attr.getAsJsonPrimitive(FTSDOWNLOAD.FILENAME).getAsString());
          ftsdownload.setPath(attr.getAsJsonPrimitive(FTSDOWNLOAD.PATH).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return ftsdownload;
      }
      else if (RESPONSE == header) {
        ftsdownload.setHeader(header);
        ftsdownload.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          ftsdownload.setSlot(attr.getAsJsonPrimitive(FTSDOWNLOAD.SLOT).getAsInt());
          ftsdownload.setFilename(attr.getAsJsonPrimitive(FTSDOWNLOAD.FILENAME).getAsString());
          ftsdownload.setPath(attr.getAsJsonPrimitive(FTSDOWNLOAD.PATH).getAsString());
          ftsdownload.setMaxDatablocks(attr.getAsJsonPrimitive(FILETRANSFER.MAXDATABLOCKS).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return ftsdownload;
      }
      else if (ERROR == header) {
        ftsdownload.setHeader(header);
        ftsdownload.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          ftsdownload.setSlot(attr.getAsJsonPrimitive(FTSDOWNLOAD.SLOT).getAsInt());
          ftsdownload.setFilename(attr.getAsJsonPrimitive(FTSDOWNLOAD.FILENAME).getAsString());
          ftsdownload.setPath(attr.getAsJsonPrimitive(FTSDOWNLOAD.PATH).getAsString());
          ftsdownload.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
          ftsdownload.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return ftsdownload;
      }

    }

    return new MESSAGE();
  }



  MESSAGE decodeHISTORYMESSAGE(String message) throws DecodeException {
    HISTORYMESSAGE history = new HISTORYMESSAGE();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.HISTORYMESSAGE.name().equals(command)) {
      if (REQUEST == header) {
        history.setCommand(Command.HISTORYMESSAGE);
        history.setHeader(REQUEST);
        history.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        history.setRoom(attr.getAsJsonPrimitive(HISTORYMESSAGE.ROOM).getAsString());
        return history;
      }
      else if (RESPONSE == header) {
        history.setCommand(Command.HISTORYMESSAGE);
        history.setHeader(RESPONSE);
        history.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        JsonArray array = attr.getAsJsonArray(HISTORYMESSAGE.RECORD);
        AttachmentImpl record[] = new AttachmentImpl[array.size()];

        for (int index = 0; index < record.length; index++) {
          record[index] = new AttachmentImpl();
          JsonObject recordobject = array.get(index).getAsJsonObject();
          JsonObject chatuserobject = recordobject.getAsJsonObject(RecordInterface.CHATUSER);
          ChatUser chatuser = new ChatUser();
          chatuser
              .setBackgroundColor(chatuserobject.getAsJsonPrimitive(ChatUser.BACKGROUND_COLOR).getAsInt());
          chatuser
              .setForegroundColor(chatuserobject.getAsJsonPrimitive(ChatUser.FOREGROUND_COLOR).getAsInt());
          chatuser.setNickname(chatuserobject.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());

          try {
            chatuser.setPseudoid(chatuserobject.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {}

          record[index].setChatUser(chatuser);
          long longvalue = recordobject.getAsJsonPrimitive(RecordInterface.DATETIME).getAsLong();
          record[index].setDatetime(longvalue);
          record[index].setMessage(recordobject.getAsJsonPrimitive(RecordInterface.MESSAGE).getAsString());
          try {
            // optional
            record[index].setAttachment(recordobject.getAsJsonPrimitive(Attachment.ATTACHMENT).getAsLong());
            try {
              record[index].setFilename(recordobject.getAsJsonPrimitive(Attachment.FILENAME).getAsString());
            }
            catch (NullPointerException e) {
              throw new DecodeException(message, "Das Attribut FILENAME wurde nicht gesetzt.");
            }
            try {
              record[index].setFilesize(recordobject.getAsJsonPrimitive(Attachment.FILESIZE).getAsLong());
            }
            catch (NullPointerException e) {
              throw new DecodeException(message, "Das Attribut FILESIZE wurde nicht gesetzt.");
            }
          }
          catch (NullPointerException e) {}
          record[index].setRoom(recordobject.getAsJsonPrimitive(RecordInterface.ROOM).getAsString());
        }

        history.setAttachment(record);
        history.setRoom(attr.getAsJsonPrimitive(HISTORYMESSAGE.ROOM).getAsString());
        return history;
      }
    }
    return new MESSAGE();
  }



  public MESSAGE decodeIMAGE(String message)
      throws DecodeException, JsonSyntaxException, UnsupportedEncodingException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.IMAGE.name().equals(command)) return new MESSAGE();
    IMAGE image = new IMAGE();
    image.setCommand(Command.IMAGE);
    image.setHeader(header);
    image.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case REQUEST:
        try {
          image.setSenderNickname(attr.getAsJsonPrimitive(IMAGE.SENDERNICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut SENDERNICKNAME wurde nicht definiert.");
        }
        try {
          image.setSenderPseudoid(attr.getAsJsonPrimitive(IMAGE.SENDERPSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: IAMGE | REQUEST, das Attribut SENDERPSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: IAMGE | REQUEST, das Attribut SENDERPSEUDOID wurde nicht definiert."
          );
        }
        try {
          image.setReceiverNickname(attr.getAsJsonPrimitive(IMAGE.RECEIVERNICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: IAMGE | REQUEST, das Attribut RECEIVERNICKNAME wurde nicht definiert.");
          throw new DecodeException(
              message,
              "Protokollfehler: IAMGE | REQUEST, das Attribut RECEIVERNICKNAME wurde nicht definiert."
          );
        }
        break;
      case RESPONSE:
        try {
          image.setSenderNickname(attr.getAsJsonPrimitive(IMAGE.SENDERNICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut SENDERNICKNAME wurde nicht definiert.");
        }
        try {
          image.setSenderPseudoid(attr.getAsJsonPrimitive(IMAGE.SENDERPSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: IMAGE | RESPONSE, das Attribut SENDERPSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: IMAGE | RESPONSE, das Attribut SENDERPSEUDOID wurde nicht definiert."
          );
        }
        try {
          image.setReceiverNickname(attr.getAsJsonPrimitive(IMAGE.RECEIVERNICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: IMAGE | RESPONSE, das Attribut RECEIVERNICKNAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: IMAGE | RESPONSE, das Attribut RECEIVERNICKNAME wurde nicht definiert."
          );
        }
        try {
          image.setConferencekey(attr.getAsJsonPrimitive(IMAGE.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
//          log.warn("Protokollfehler: IMAGE | RESPONSE, das Attribut CONFERENCEKEY wurde nicht definiert.");
//          throw new DecodeException(
//              message, "Protokollfehler: IMAGE | RESPONSE, das Attribut CONFERENCEKEY wurde nicht definiert."
//          );
        }
        break;
      case CONFIRM:
        break;
      case ERROR:
        try {
          image.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut MULTILINGUALKEY wurde nicht definiert.");
        }
        try {
          image.setSenderNickname(attr.getAsJsonPrimitive(IMAGE.SENDERNICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut SENDERNICKNAME wurde nicht definiert.");
        }
        try {
          image.setSenderPseudoid(attr.getAsJsonPrimitive(IMAGE.SENDERPSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: IAMGE | ERROR, das Attribut SENDERPSEUDOID wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: IAMGE | ERROR, das Attribut SENDERPSEUDOID wurde nicht definiert."
          );
        }
        try {
          image.setReceiverNickname(attr.getAsJsonPrimitive(IMAGE.RECEIVERNICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut RECEIVERNICKNAME wurde nicht definiert.");
        }

        break;
    }
    return image;
  }



  MESSAGE decodeINCOMINGCALL(String message) throws DecodeException {
    INCOMINGCALL incoming = new INCOMINGCALL();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.INCOMINGCALL.name().equals(command)) return new MESSAGE();
    incoming.setCommand(Command.INCOMINGCALL);
    incoming.setHeader(header);
    if (RESPONSE == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      incoming.setDataset(Protocol.DATASET);
      try {
        incoming.setCallerNickname(attr.get(INCOMINGCALL.CALLER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setCallerPseudoid(attr.get(INCOMINGCALL.CALLER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setCallerVoice(attr.get(INCOMINGCALL.CALLER_VOICE).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }

      try {
        incoming.setReceiverVoice(attr.get(INCOMINGCALL.RECEIVER_VOICE).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: INCOMINGCALL | RESPONSE, das Attribut RECEIVER_VOICE wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: INCOMINGCALL | RESPONSE, das Attribut RECEIVER_VOICE wurde nicht definiert."
        );
      }

      try {
        incoming.setReceiverPseudoid(attr.get(INCOMINGCALL.RECEIVER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setReceiverNickname(attr.get(INCOMINGCALL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setReceiverSession(attr.get(INCOMINGCALL.RECEIVER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: INCOMINGCALL | RESPONSE, das Attribut RECEIVER_SESSION wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: INCOMINGCALL | RESPONSE, das Attribut RECEIVER_SESSION wurde nicht definiert."
        );
      }
      try {
        incoming.setCallerSession(attr.get(INCOMINGCALL.CALLER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setConferencekey(attr.get(INCOMINGCALL.CONFERENCEKEY).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: CONFERENCEKEY | RESPONSE, das Attribut CONFERENCEKEY wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: CONFERENCEKEY | RESPONSE, das Attribut CONFERENCEKEY wurde nicht definiert."
        );
      }

    }
    else if (REQUEST == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      incoming.setDataset(Protocol.DATASET);
      try {
        incoming.setCallerNickname(attr.get(INCOMINGCALL.CALLER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut NICKNAME wurde nicht definiert.");
      }
      try {
        incoming.setCallerPseudoid(attr.get(INCOMINGCALL.CALLER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut USERID wurde nicht definiert.");
      }
      try {
        incoming.setCallerVoice(attr.get(INCOMINGCALL.CALLER_VOICE).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_VOICE wurde nicht definiert.");
      }
      try {
        incoming.setCallerSession(attr.get(INCOMINGCALL.CALLER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut CALLER_SESSION wurde nicht definiert.");
      }
      try {
        incoming.setReceiverPseudoid(attr.get(INCOMINGCALL.RECEIVER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_USERID wurde nicht definiert.");
      }
      try {
        incoming.setReceiverNickname(attr.get(INCOMINGCALL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
      }
      try {
        incoming.setReceiverSession(attr.get(INCOMINGCALL.RECEIVER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut RECEIVER_SESSION wurde nicht definiert.");
      }
      try {
        incoming.setConferencekey(attr.get(INCOMINGCALL.CONFERENCEKEY).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: CONFERENCEKEY | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: CONFERENCEKEY | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
        );
      }

    }
    else if (ERROR == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      incoming.setDataset(Protocol.DATASET);
      try {
        incoming.setReceiverNickname(attr.get(INCOMINGCALL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setErrorMessage(attr.get(MESSAGE.ERRORMESSAGE).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setMultilingualkey(
            KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
        );
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut MULTILINGUALKEY wurde nicht definiert.");
      }
    }
    else if (CONFIRM == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      incoming.setDataset(Protocol.DATASET);
      try {
        incoming.setCallerNickname(attr.get(INCOMINGCALL.CALLER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setCallerVoice(attr.get(INCOMINGCALL.CALLER_VOICE).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: INCOMINGCALL | CONFIRM, das Attribut CALLER_VOICE wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: INCOMINGCALL | CONFIRM, das Attribut CALLER_VOICE wurde nicht definiert."
        );

      }
      try {
        incoming.setReceiverPseudoid(attr.get(INCOMINGCALL.RECEIVER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setReceiverNickname(attr.get(INCOMINGCALL.RECEIVER_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setCallerPseudoid(attr.get(INCOMINGCALL.CALLER_PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setReceiverSession(attr.get(INCOMINGCALL.RECEIVER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        // optional
      }
      try {
        incoming.setCallerSession(attr.get(INCOMINGCALL.CALLER_SESSION).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: INCOMINGCALL | CONFIRM, das Attribut CALLER_SESSION wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: INCOMINGCALL | CONFIRM, das Attribut CALLER_SESSION wurde nicht definiert."
        );
      }
      try {
        incoming.setConferencekey(attr.get(INCOMINGCALL.CONFERENCEKEY).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal(
            "Protokollfehler: INCOMINGCALL | CONFIRM, das Attribut CONFERENCEKEY wurde nicht definiert."
        );
        throw new DecodeException(
            message,
            "Protokollfehler: INCOMINGCALL | CONFIRM, das Attribut CONFERENCEKEY wurde nicht definiert."
        );
      }

    }
    return incoming;
  }



  MESSAGE decodeKEEPALIVE(String message) throws DecodeException {
    KEEPALIVE keepalive = new KEEPALIVE();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonObject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonObject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonObject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.KEEPALIVE.name().equals(command)) {
      if (REQUEST == header) {
        keepalive.setCommand(Command.KEEPALIVE);
        keepalive.setHeader(REQUEST);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) return keepalive;
        keepalive.setDataset(Protocol.DATASET);
        try {
          keepalive.setSessionId(attr.getAsJsonPrimitive(KEEPALIVE.SESSIONID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Die SESSIONID ist nicht gesetzt");
        }
        return keepalive;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeLEAVEPRIVATECHAT(String message) throws DecodeException {
    LEAVEPRIVATECHAT call = new LEAVEPRIVATECHAT();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.LEAVEPRIVATECHAT.name().equals(command)) {
      if (REQUEST == header) {
        call.setCommand(Command.LEAVEPRIVATECHAT);
        call.setHeader(REQUEST);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setRemotePseudoid(attr.getAsJsonPrimitive(LEAVEPRIVATECHAT.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: LEAVEPRIVATECHAT | REQUEST, das Attribut GONE_SESSIONID wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: LEAVEPRIVATECHAT | REQUEST, das Attribut GONE_SESSIONID wurde nicht gesetzt."
          );
        }
        return call;
      }
      else if (RESPONSE == header) {
        call.setCommand(Command.LEAVEPRIVATECHAT);
        call.setHeader(RESPONSE);
        call.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          call.setParticipant(attr.getAsJsonPrimitive(LEAVEPRIVATECHAT.PARTICIPANT).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: LEAVEPRIVATECHAT | RESPONSE, das Attribut PARTICIPANT wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: LEAVEPRIVATECHAT | RESPONSE, das Attribut PARTICIPANT wurde nicht gesetzt."
          );
        }
        try {
          call.setRemotePseudoid(attr.getAsJsonPrimitive(LEAVEPRIVATECHAT.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: LEAVEPRIVATECHAT | RESPONSE, das Attribut REMOTE_PSEUDOID wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: LEAVEPRIVATECHAT | RESPONSE, das Attribut REMOTE_PSEUDOID wurde nicht gesetzt."
          );
        }
        return call;
      }
    }

    return new MESSAGE();
  }



  MESSAGE decodeLEAVEROOM(String message) throws DecodeException {
    LEAVEROOM leaveroom = new LEAVEROOM();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.LEAVEROOM.name().equals(command)) {
      leaveroom.setCommand(Command.LEAVEROOM);
      if (REQUEST == header) {
        leaveroom.setHeader(header);
        leaveroom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          leaveroom.setRoom(attr.getAsJsonPrimitive(LEAVEROOM.ROOM).getAsString());
          leaveroom.setPseudoid(attr.getAsJsonPrimitive(LEAVEROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "LEAVEROOM-REQUEST, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return leaveroom;
      }
      else if (RESPONSE == header) {
        leaveroom.setHeader(header);
        leaveroom.setHeader(header);
        leaveroom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          leaveroom.setRoom(attr.getAsJsonPrimitive(LEAVEROOM.ROOM).getAsString());
          leaveroom.setPseudoid(attr.getAsJsonPrimitive(LEAVEROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(
              message, "LEAVEROOM-RESPONSE, ein Attribut in DATASET wurde nicht gesetzt."
          );
        }
        return leaveroom;
      }
      else if (ERROR == header) {
        leaveroom.setHeader(header);
        leaveroom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          leaveroom.setRoom(attr.getAsJsonPrimitive(LEAVEROOM.ROOM).getAsString());
          leaveroom.setPseudoid(attr.getAsJsonPrimitive(LEAVEROOM.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "LEAVEROOM-ERROR, ein Attribut in DATASET wurde nicht gesetzt.");
        }
        return leaveroom;
      }
    }

    return new MESSAGE();
  }



  MESSAGE decodeMICROERROR(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.MICROERROR.name().equals(command)) return new MESSAGE();
    MICROERROR microerror = new MICROERROR();
    microerror.setCommand(Command.MICROERROR);
    microerror.setHeader(header);
    if (REQUEST == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      microerror.setDataset(Protocol.DATASET);
      try {
        microerror.setFromNickname(attr.get(MICROERROR.FROM_NICKNAME).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut FROM_NICKNAME wurde nicht definiert.");
      }
      try {
        microerror.setFromUserid(attr.get(MICROERROR.FROM_USERID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut FROM_USERID wurde nicht definiert.");
      }
      try {
        microerror.setText(attr.get(MESSAGE.TEXT).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut FROM_USERID wurde nicht definiert.");
      }
      try {
        microerror.setToUserid(attr.get(MICROERROR.TO_USERID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut TO_USERID wurde nicht definiert.");
      }
    }
    return microerror;
  }



  MESSAGE decodeONCALL(String message) throws DecodeException {
    ONCALL oncall = new ONCALL();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.ONCALL.name().equals(command)) return new MESSAGE();
    oncall.setCommand(Command.ONCALL);
    oncall.setHeader(header);
    if (REQUEST == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      oncall.setDataset(Protocol.DATASET);
      try {
        oncall.setPseudoid(attr.get(ONCALL.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal("Protokollfehler: REQUEST | ONCALL, das Attribut PSEUDOID wurde nicht definiert.");
        throw new DecodeException(
            message, "Protokollfehler: REQUEST | ONCALL, das Attribut PSEUDOID wurde nicht definiert."
        );
      }
      try {
        oncall.setOnCall(attr.get(ONCALL.ONCALL).getAsBoolean());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut ONCALL wurde nicht definiert.");
      }
    }
    else if (RESPONSE == header) {
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      oncall.setDataset(Protocol.DATASET);
      try {
        oncall.setPseudoid(attr.get(ONCALL.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal("Protokollfehler: RESPONSE | ONCALL, das Attribut PSEUDOID wurde nicht definiert.");
        throw new DecodeException(
            message, "Protokollfehler: RESPONSE | ONCALL, das Attribut PSEUDOID wurde nicht definiert."
        );
      }
      try {
        oncall.setOnCall(attr.get(ONCALL.ONCALL).getAsBoolean());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut ONCALL wurde nicht definiert.");
      }
    }
    return oncall;
  }



  MESSAGE decodeONHOOK(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.ONHOOK.name().equals(command)) return new MESSAGE();
    ONHOOK onhook = new ONHOOK();
    onhook.setCommand(Command.ONHOOK);
    onhook.setHeader(header);

    switch(header) {
      case REQUEST:
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        onhook.setDataset(Protocol.DATASET);
        try {
          onhook.setCallerPseudoid(attr.get(ONHOOK.CALLER_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: ONHOOK | REQUEST, das Attribut CALLER_PSEUDOID wurde nicht definiert.");
          throw new DecodeException(message, "Das Attribut CALLER_PSEUDOID wurde nicht definiert.");
        }
        try {
          onhook.setReceiverPseudoid(attr.get(ONHOOK.RECEIVER_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: ONHOOK | REQUEST, das Attribut RECEIVER_PSEUDOID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: ONHOOK | REQUEST, das Attribut RECEIVER_PSEUDOID wurde nicht definiert."
          );
        }
        try {
          onhook.setTo(attr.get(ONHOOK.TO).getAsBoolean());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: ONHOOK | REQUEST, das Attribut TO wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: ONHOOK | REQUEST, das Attribut TO wurde nicht definiert."
          );
        }
        try {
          onhook.setSignal(attr.get(ONHOOK.SIGNAL).getAsBoolean());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: ONHOOK | REQUEST, das Attribut SIGNAL wurde nicht definiert.");
          throw new DecodeException(
              message, "Protokollfehler: ONHOOK | REQUEST, das Attribut SIGNAL wurde nicht definiert."
          );
        }
        try {
          onhook.setConferencekey(attr.get(ONHOOK.CONFERENCEKEY).getAsString());
        }
        catch (NullPointerException e) {
//          log.fatal("Protokollfehler: ONHOOK | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert.");
//          throw new DecodeException(
//              message, "Protokollfehler: ONHOOK | REQUEST, das Attribut CONFERENCEKEY wurde nicht definiert."
//          );
        }

        break;
      case RESPONSE:
        attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        onhook.setDataset(Protocol.DATASET);
        try {
          onhook.setCallerPseudoid(attr.get(ONHOOK.CALLER_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut CALLER_USERID wurde nicht definiert.");
        }
        try {
          onhook.setReceiverPseudoid(attr.get(ONHOOK.RECEIVER_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut RECEIVER_USERID wurde nicht definiert.");
        }
        try {
          onhook.setTo(attr.get(ONHOOK.TO).getAsBoolean());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut TO wurde nicht definiert.");
        }
        break;
    }

    return onhook;
  }



  public MESSAGE decodePRIVATECHATFILE(String message)
      throws DecodeException, JsonSyntaxException, UnsupportedEncodingException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.PRIVATECHATFILE.name().equals(command)) return new MESSAGE();
    PRIVATECHATFILE privatechatfile = new PRIVATECHATFILE();
    privatechatfile.setCommand(Command.PRIVATECHATFILE);
    privatechatfile.setHeader(header);
    privatechatfile.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case REQUEST:
        try {
          privatechatfile.setPseudoid(attr.getAsJsonPrimitive(PRIVATECHATFILE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut PSEUDOID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut PSEUDOID wurde nicht definiert."
          );
        }
        try {
          privatechatfile
              .setAbsoluteFilename(attr.getAsJsonPrimitive(PRIVATECHATFILE.ABSOLUTE_FILENAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut ABSOLUTE_FILENAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut ABSOLUTE_FILENAME wurde nicht definiert."
          );
        }
        try {
          privatechatfile.setFilename(attr.getAsJsonPrimitive(PRIVATECHATFILE.FILENAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut FILENAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut FILENAME wurde nicht definiert."
          );
        }
        privatechatfile.setFilesize(attr.getAsJsonPrimitive(PRIVATECHATFILE.FILESIZE).getAsLong());
        try {
          privatechatfile.setMessage(attr.getAsJsonPrimitive(PRIVATECHATFILE.MESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut MESSAGE wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut MESSAGE wurde nicht definiert."
          );
        }
        try {
          privatechatfile
              .setRemotePseudoid(attr.getAsJsonPrimitive(PRIVATECHATFILE.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut REMOTE_SESSION_ID wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut REMOTE_SESSION_ID wurde nicht definiert."
          );
        }
        try {
          privatechatfile
              .setRemoteNickname(attr.getAsJsonPrimitive(PRIVATECHATFILE.REMOTE_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut REMOTE_NICKNAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: REQUEST | PRIVATECHATFILE, das Attribut REMOTE_NICKNAME wurde nicht definiert."
          );
        }
        break;
      case RESPONSE:
        try {
          privatechatfile.setNumber(attr.getAsJsonPrimitive(PRIVATECHATFILE.NUMBER).getAsLong());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: RESPONSE | PRIVATECHATFILE, das Attribut NUMBER wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: RESPONSE | PRIVATECHATFILE, das Attribut NUMBER wurde nicht definiert."
          );
        }
        try {
          privatechatfile
              .setRemoteNickname(attr.getAsJsonPrimitive(PRIVATECHATFILE.REMOTE_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: RESPONSE | PRIVATECHATFILE, das Attribut REMOTE_NICKNAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: RESPONSE | PRIVATECHATFILE, das Attribut REMOTE_NICKNAME wurde nicht definiert."
          );
        }
        try {
          privatechatfile
              .setAbsoluteFilename(attr.getAsJsonPrimitive(PRIVATECHATFILE.ABSOLUTE_FILENAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: RESPONSE | PRIVATECHATFILE, das Attribut ABSOLUTE_FILENAME wurde nicht definiert."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: RESPONSE | PRIVATECHATFILE, das Attribut ABSOLUTE_FILENAME wurde nicht definiert."
          );
        }
        try {
          privatechatfile.setPseudoid(attr.getAsJsonPrimitive(PRIVATECHATFILE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          privatechatfile.setFilename(attr.getAsJsonPrimitive(PRIVATECHATFILE.FILENAME).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          privatechatfile
              .setRemotePseudoid(attr.getAsJsonPrimitive(PRIVATECHATFILE.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          privatechatfile.setMessage(attr.getAsJsonPrimitive(PRIVATECHATFILE.MESSAGE).getAsString());
        }
        catch (NullPointerException e) {}
        privatechatfile.setFilesize(attr.getAsJsonPrimitive(PRIVATECHATFILE.FILESIZE).getAsLong());
        break;
      case CONFIRM:
        break;
      case ERROR:
        break;
    }
    return privatechatfile;
  }



  MESSAGE decodePRIVATEMESSAGE(String message) throws DecodeException {
    PRIVATEMESSAGE chatmessage = new PRIVATEMESSAGE();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.PRIVATEMESSAGE.name().equals(command)) {
      chatmessage.setCommand(Command.PRIVATEMESSAGE);
      if (REQUEST == header) {
        chatmessage.setHeader(REQUEST);
        chatmessage.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          chatmessage.setPseudoid(attr.getAsJsonPrimitive(PRIVATEMESSAGE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          chatmessage
              .setRemotePseudoid(attr.getAsJsonPrimitive(PRIVATEMESSAGE.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut REMOTE_PSEUDOID wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut REMOTE_PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          chatmessage.setMessage(attr.getAsJsonPrimitive(PRIVATEMESSAGE.MESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut MESSAGE wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut MESSAGE wurde nicht gesetzt."
          );
        }
        try {
          long number = attr.getAsJsonPrimitive(PRIVATEMESSAGE.DATETIME).getAsLong();
          chatmessage.setDatetime(number);
        }
        catch (NullPointerException e) {}

        JsonObject chatuser = attr.getAsJsonObject(PRIVATEMESSAGE.CHATUSER);
        if (chatuser != null) {
          ChatUser user = new ChatUser();
          int number = chatuser.getAsJsonPrimitive(ChatUser.BACKGROUND_COLOR).getAsInt();
          user.setBackgroundColor(number);
          number = chatuser.getAsJsonPrimitive(ChatUser.FOREGROUND_COLOR).getAsInt();
          user.setForegroundColor(number);

          try {
            user.setNickname(chatuser.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut NICKNAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: PRIVATEMESSAGE | REQUEST, das Attribut NICKNAME wurde nicht gesetzt."
            );
          }

          try {
            user.setPseudoid(chatuser.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // optional
          }
          chatmessage.setChatUser(user);
        }

        try {
          chatmessage.setAttachment(attr.getAsJsonPrimitive(Attachment.ATTACHMENT).getAsLong());
        }
        catch (NullPointerException e) {}
        try {
          chatmessage.setFilename(attr.getAsJsonPrimitive(Attachment.FILENAME).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          chatmessage.setFilesize(attr.getAsJsonPrimitive(Attachment.FILESIZE).getAsLong());
        }
        catch (NullPointerException e) {}

        return chatmessage;
      }
      else if (RESPONSE == header) {
        chatmessage.setHeader(RESPONSE);
        chatmessage.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          chatmessage.setPseudoid(attr.getAsJsonPrimitive(PRIVATEMESSAGE.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: PRIVATEMESSAGE | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message,
              "Protokollfehler: PRIVATEMESSAGE | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }

        try {
          chatmessage
              .setRemotePseudoid(attr.getAsJsonPrimitive(PRIVATEMESSAGE.REMOTE_PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal(
              "Protokollfehler: PRIVATEMESSAGE | RESPONSE, das Attribut REMOTE_PSEUDOID wurde nicht gesetzt."
          );
          throw new DecodeException(
              message,
              "Protokollfehler: PRIVATEMESSAGE | RESPONSE, das Attribut REMOTE_PSEUDOID wurde nicht gesetzt."
          );
        }

        try {
          chatmessage.setMessage(attr.getAsJsonPrimitive(PRIVATEMESSAGE.MESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: PRIVATEMESSAGE | RESPONSE, das Attribut MESSAGE wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: PRIVATEMESSAGE | RESPONSE, das Attribut MESSAGE wurde nicht gesetzt."
          );
        }
        try {
          long number = attr.getAsJsonPrimitive(PRIVATEMESSAGE.DATETIME).getAsLong();
          chatmessage.setDatetime(number);
        }
        catch (NullPointerException e) {}
        JsonObject chatuser = attr.getAsJsonObject(PRIVATEMESSAGE.CHATUSER);
        if (chatuser != null) {
          ChatUser user = new ChatUser();
          int number = chatuser.getAsJsonPrimitive(ChatUser.BACKGROUND_COLOR).getAsInt();
          user.setBackgroundColor(number);
          number = chatuser.getAsJsonPrimitive(ChatUser.FOREGROUND_COLOR).getAsInt();
          user.setForegroundColor(number);

          try {
            user.setNickname(chatuser.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: PRIVATEMESSAGE | RESPONSE | CHATUSER | NICKNAME, das Attribut NICKNAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: PRIVATEMESSAGE | RESPONSE | CHATUSER | NICKNAME, das Attribut NICKNAME wurde nicht gesetzt."
            );
          }

          try {
            user.setPseudoid(chatuser.getAsJsonPrimitive(ChatUser.PSEUDOID).getAsString());
          }
          catch (NullPointerException e) {
            // optional
          }
          chatmessage.setChatUser(user);
        }
        try {
          chatmessage.setAttachment(attr.getAsJsonPrimitive(Attachment.ATTACHMENT).getAsLong());
        }
        catch (NullPointerException e) {}
        try {
          chatmessage.setFilename(attr.getAsJsonPrimitive(Attachment.FILENAME).getAsString());
        }
        catch (NullPointerException e) {}
        try {
          chatmessage.setFilesize(attr.getAsJsonPrimitive(Attachment.FILESIZE).getAsLong());
        }
        catch (NullPointerException e) {}

        return chatmessage;
      }
    }
    return new MESSAGE();
  }



  public MESSAGE decodePROYECTORCLOSING(String message)
      throws DecodeException, JsonSyntaxException, UnsupportedEncodingException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.PROYECTORCLOSING.name().equals(command)) return new MESSAGE();
    PROYECTORCLOSING proyector = new PROYECTORCLOSING();
    proyector.setCommand(Command.PROYECTORCLOSING);
    proyector.setHeader(header);
    proyector.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case RESPONSE:
        try {
          proyector.setPseudoid(attr.getAsJsonPrimitive(PROYECTORCLOSING.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: PROYECTORCLOSING | RESPONSE, das Attribut PSEUDOID fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: PROYECTORCLOSING | RESPONSE, das Attribut PSEUDOID fehlt."
          );
        }
        break;
      case REQUEST:
        try {
          proyector.setPseudoid(attr.getAsJsonPrimitive(PROYECTORCLOSING.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: PROYECTORCLOSING | REQUEST, das Attribut PSEUDOID fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: PROYECTORCLOSING | REQUEST, das Attribut PSEUDOID fehlt."
          );
        }
        break;
    }
    return proyector;
  }



  public MESSAGE decodeREADROOMS(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.READROOMS.name().equals(command)) return new MESSAGE();
    READROOMS readrooms = new READROOMS();
    readrooms.setCommand(Command.READROOMS);
    readrooms.setHeader(header);
    readrooms.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
    switch(header) {
      case REQUEST:
        try {
          readrooms.setPseudoid(attr.getAsJsonPrimitive(READROOMS.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READROOMS | REQUEST, das Attribut PSEUDOID fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: READROOMS | REQUEST, das Attribut PSEUDOID fehlt."
          );
        }
        try {
          readrooms.setRoomtype(Roomtype.toRoomtype(attr.getAsJsonPrimitive(READROOMS.ROOMTYPE).getAsInt()));
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READROOMS | REQUEST, das Attribut ROOMTYPE fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: READROOMS | REQUEST, das Attribut ROOMTYPE fehlt."
          );
        }
        break;
      case RESPONSE:
        try {
          readrooms.setPseudoid(attr.getAsJsonPrimitive(READROOMS.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READROOMS | RESPONSE, das Attribut PSEUDOID fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: READROOMS | RESPONSE, das Attribut PSEUDOID fehlt."
          );
        }
        try {
          readrooms.setRoomtype(Roomtype.toRoomtype(attr.getAsJsonPrimitive(READROOMS.ROOMTYPE).getAsInt()));
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READROOMS | RESPONSE, das Attribut ROOMTYPE fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: READROOMS | RESPONSE, das Attribut ROOMTYPE fehlt."
          );
        }
        try {
          JsonArray jsonarray = attr.getAsJsonArray(READROOMS.ROOMS);
          String[] rooms = new String[jsonarray.size()];
          for (int index = 0; index < rooms.length; index++) {
            rooms[index] = jsonarray.get(index).getAsString();
          }
          readrooms.setRooms(rooms);
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOMS wurde nicht definiert.");
        }
        break;
    }

    return readrooms;
  }



  MESSAGE decodeREADTOPICROOMOWNER(String message) throws DecodeException {
    READTOPICROOMOWNER temproom = new READTOPICROOMOWNER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.READTOPICROOMOWNER.name().equals(command)) {
      temproom.setCommand(Command.READTOPICROOMOWNER);
      if (REQUEST == header) {
        temproom.setHeader(header);
        temproom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          temproom.setOwner(attr.getAsJsonPrimitive(READTOPICROOMOWNER.OWNER).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READTOPICROOMOWNER | REQUEST, das Attribut OWNER fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: READTOPICROOMOWNER | REQUEST, das Attribut OWNER fehlt."
          );
        }
        try {
          temproom.setPseudoid(attr.getAsJsonPrimitive(READTOPICROOMOWNER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READTOPICROOMOWNER | REQUEST, das Attribut PSEUDOID fehlt.");
          throw new DecodeException(message, "Das Attribut PSEUDOID wurde nicht definiert.");
        }
        return temproom;
      }
      else if (RESPONSE == header) {
        temproom.setHeader(header);
        temproom.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          temproom.setOwner(attr.getAsJsonPrimitive(READTOPICROOMOWNER.OWNER).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READTOPICROOMOWNER | RESPONSE, das Attribut OWNER fehlt.");
          throw new DecodeException(
              message, "Protokollfehler: READTOPICROOMOWNER | RESPONSE, das Attribut OWNER fehlt."
          );
        }
        try {
          temproom.setPseudoid(attr.getAsJsonPrimitive(READTOPICROOMOWNER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: READTOPICROOMOWNER | RESPONSE, das Attribut PSEUDOID fehlt.");
          throw new DecodeException(message, "Das Attribut PSEUDOID wurde nicht definiert.");
        }
        // rooms decodieren
        JsonArray jsonarray = attr.getAsJsonArray(ROOMLIST.ROOMLIST);
        Room room[] = new Room[jsonarray.size()];
        for (int index = 0; index < room.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          room[index] = new Room();
          room[index].setChatid(objectroom.getAsJsonPrimitive(Room.ROOM).getAsString());
          room[index].setEntry(Entry.valueOf(objectroom.getAsJsonPrimitive(Room.ENTRY).getAsString()));
          room[index]
              .setLifetime(Lifetime.valueOf(objectroom.getAsJsonPrimitive(Room.LIFETIME).getAsString()));
          try {
            room[index].setOwner(objectroom.getAsJsonPrimitive(Room.OWNER).getAsString());
          }
          catch (NullPointerException e) {
            room[index].setOwner(new String());
          }
        }
        temproom.setRoom(room);
        return temproom;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeROOMLIST(String message) throws DecodeException {
    ROOMLIST roomlist = new ROOMLIST();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.ROOMLIST.name().equals(command)) {
      roomlist.setCommand(Command.ROOMLIST);
      if (RESPONSE == header) {
        roomlist.setHeader(RESPONSE);
        roomlist.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");

        JsonArray jsonarray = attr.getAsJsonArray(ROOMLIST.ROOMLIST);
        Room room[] = new Room[jsonarray.size()];
        for (int index = 0; index < room.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          room[index] = new Room();
          try {
            room[index].setChatid(objectroom.getAsJsonPrimitive(Room.ROOM).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal("Protokollfehler: ROOMLIST | RESPONSE, das Attribut ROOM fehlt.");
            throw new DecodeException(
                message, "Protokollfehler: ROOMLIST | RESPONSE, das Attribut ROOM fehlt."
            );
          }
          room[index].setEntry(Entry.valueOf(objectroom.getAsJsonPrimitive(Room.ENTRY).getAsString()));
          room[index]
              .setLifetime(Lifetime.valueOf(objectroom.getAsJsonPrimitive(Room.LIFETIME).getAsString()));
          room[index]
              .setRoomtype(Roomtype.valueOf(objectroom.getAsJsonPrimitive(Room.ROOMTYPE).getAsString()));
          try {
            room[index].setOwner(objectroom.getAsJsonPrimitive(Room.OWNER).getAsString());
          }
          catch (NullPointerException e) {
            room[index].setOwner(new String());
          }
        }
        roomlist.setRoom(room);
        return roomlist;
      }
      else if (REQUEST == header) {
        roomlist.setHeader(REQUEST);
        return roomlist;
      }
      else if (CONFIRM == header) {}
      else if (ERROR == header) {}
    }
    return new MESSAGE();
  }



  public MESSAGE decodeSCREENCAST(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.SCREENCAST.name().equals(command)) return new MESSAGE();
    SCREENCAST screencast = new SCREENCAST();
    screencast.setCommand(Command.SCREENCAST);
    screencast.setHeader(header);
    screencast.setDataset(Protocol.DATASET);
    JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);

    switch(header) {
      case REQUEST:

        try {
          screencast.setCallerUserid(attr.getAsJsonPrimitive(SCREENCAST.CALLER_USERID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut CALLER_USERID wurde nicht definiert.");
        }
        try {
          screencast.setCallerNickname(attr.getAsJsonPrimitive(SCREENCAST.CALLER_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut CALLER_NICKNAME wurde nicht definiert.");
        }
        try {
          screencast.setCallerIp(attr.getAsJsonPrimitive(SCREENCAST.CALLER_IP).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut CALLER_IP wurde nicht definiert.");
        }
        try {
          screencast.setCallerPort(attr.getAsJsonPrimitive(SCREENCAST.CALLER_PORT).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut CALLER_PORT wurde nicht definiert.");
        }
        try {
          screencast.setReceiverNickname(attr.getAsJsonPrimitive(SCREENCAST.RECEIVER_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
        }

        break;
      case RESPONSE:
        try {
          screencast.setCallerUserid(attr.getAsJsonPrimitive(SCREENCAST.CALLER_USERID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut CALLER_USERID wurde nicht definiert.");
        }
        try {
          screencast.setReceiverUserid(attr.getAsJsonPrimitive(SCREENCAST.RECEIVER_USERID).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut RECEIVER_USERID wurde nicht definiert.");
        }
        try {
          screencast.setReceiverNickname(attr.getAsJsonPrimitive(SCREENCAST.RECEIVER_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
        }
        break;
      case CONFIRM:
        break;
      case ERROR:
        try {
          screencast.setReceiverNickname(attr.getAsJsonPrimitive(SCREENCAST.RECEIVER_NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut RECEIVER_NICKNAME wurde nicht definiert.");
        }
        screencast.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        try {
          screencast.setReceiverUserid(attr.getAsJsonPrimitive(SCREENCAST.RECEIVER_USERID).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }
        break;
    }

    return screencast;
  }



  MESSAGE decodeSEARCHFILES(String message) throws DecodeException {
    SEARCHFILES searchfiles = new SEARCHFILES();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.SEARCHFILES.name().equals(command)) {
      searchfiles.setCommand(Command.SEARCHFILES);
      if (REQUEST == header) {
        searchfiles.setHeader(REQUEST);
        searchfiles.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        searchfiles.setUserid(attr.getAsJsonPrimitive(SEARCHFILES.USERID).getAsString());
        JsonArray jsonarray = attr.getAsJsonArray(SEARCHFILES.SEARCHFILES);
        String files[] = new String[jsonarray.size()];
        for (int index = 0; index < files.length; index++) {
          JsonObject objectfile = jsonarray.get(index).getAsJsonObject();
          files[index] = objectfile.getAsJsonPrimitive(SEARCHFILES.PATTERN).getAsString();
        }
        searchfiles.setPatterns(files);
        return searchfiles;
      }
      else if (RESPONSE == header) {
        searchfiles.setCommand(Command.SEARCHFILES);
        searchfiles.setHeader(RESPONSE);
        searchfiles.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        searchfiles.setUserid(attr.getAsJsonPrimitive(SEARCHFILES.USERID).getAsString());
        try {
          searchfiles.setStarted(attr.getAsJsonPrimitive(SEARCHFILES.START).getAsBoolean());
        }
        catch (NullPointerException e) {
          searchfiles.setStarted(false);
        }
        JsonArray jsonarray = attr.getAsJsonArray(SEARCHFILES.SEARCHFILE);
        int count = jsonarray.size();
        Searchfile[] files = new Searchfile[count];
        for (int index = 0; index < count; index++) {
          jsonobject = jsonarray.get(index).getAsJsonObject();
          files[index] = new Searchfile();
          files[index].setFilename(jsonobject.getAsJsonPrimitive(Searchfile.FILENAME).getAsString());
          files[index].setIndex(jsonobject.getAsJsonPrimitive(Searchfile.INDEX).getAsInt());
          try {
            files[index].setFilesize(jsonobject.getAsJsonPrimitive(Searchfile.FILESIZE).getAsLong());
          }
          catch (NullPointerException e) {
            throw new DecodeException(message, "Das Attribut FILESIZE ist nicht gesetzt");
          }
        }
        searchfiles.setSearchfiles(files);
        return searchfiles;
      }
    }
    return new MESSAGE();
  }



  /**
   * 
   * @param message
   * @return
   * @throws DecodeException
   */
  MESSAGE decodeSIGNIN(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonObject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonObject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonObject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.SIGNIN.name().equals(command)) {
      if (REQUEST == header) {
        SIGNIN signin = new SIGNIN();
        signin.setHeader(header);
        signin.setCommand(Command.SIGNIN);
        signin.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        JsonPrimitive email = attr.getAsJsonPrimitive(USER.EMAIL);
        if (email == null) throw new DecodeException(message, "Das Attribut EMAIL wurde nicht gesetzt");
        signin.setEmail(email.getAsString());
        return signin;
      }
      else if (CONFIRM == header) {
        SIGNIN signin = new SIGNIN();
        signin.setHeader(header);
        signin.setCommand(Command.SIGNIN);
        signin.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          signin.setEmail(attr.getAsJsonPrimitive(SIGNIN.EMAIL).getAsString());
          signin.setNickname(attr.getAsJsonPrimitive(SIGNIN.NICKNAME).getAsString());
          signin.setPassword(attr.getAsJsonPrimitive(SIGNIN.PASSWORD).getAsString());
          signin.setForegroundColor(attr.getAsJsonPrimitive(SIGNIN.FOREGROUND_COLOR).getAsInt());
          signin.setBackgroundColor(attr.getAsJsonPrimitive(SIGNIN.BACKGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "SIGNIN-CONFIRM, ein Attribut in DATASET wurde nicht gesetzt.");
        }
        try {
          // optional, weil es abwärts kompatibel sein muss
          signin.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {}
        try {
          // optional, weil es abwärts kompatibel sein muss
          signin.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {}
        return signin;
      }
      else if (ERROR == header) {
        SIGNIN signin = new SIGNIN();
        signin.setHeader(header);
        signin.setCommand(Command.SIGNIN);
        signin.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");

        try {
          signin.setText(attr.getAsJsonPrimitive(MESSAGE.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          // optional
        }

        try {
          signin.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {}

        try {
          signin.setEmail(attr.getAsJsonPrimitive(USER.EMAIL).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | ERROR, das Attribut EMAIL wurde nicht gesetzt.");
          throw new DecodeException(message, "SIGNIN | ERROR, das Attribut EMAIL wurde nicht gesetzt.");
        }
        try {
          signin.setErrorCode(attr.getAsJsonPrimitive(MESSAGE.ERRORCODE).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | ERROR, das Attribut in ERRORCODE wurde nicht gesetzt.");
          throw new DecodeException(
              message, "SIGNIN | ERROR, das Attribut in ERRORCODE wurde nicht gesetzt."
          );
        }
        try {
          // optional, weil es abwärts kompatible sein muss
          signin.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(MESSAGE.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {}

        return signin;
      }
      else if (RESPONSE == header) {
        SIGNIN signin = new SIGNIN();
        signin.setHeader(header);
        signin.setCommand(Command.SIGNIN);
        signin.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);

        try {
          signin.setNeuesPassword(attr.getAsJsonPrimitive(SIGNIN.NEUES_PASSWORD).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut NEUES_PASSWORD wurde nicht gesetzt.");
          throw new DecodeException(
              message, "SIGNIN | RESPONSE, das Attribut NEUES_PASSWORD wurde nicht gesetzt."
          );
        }

        try {
          signin.setConfirmationKey(attr.getAsJsonPrimitive(SIGNIN.CONFIRMATION_KEY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut CONFIRMATION_KEY wurde nicht gesetzt.");
          throw new DecodeException(
              message, "SIGNIN | RESPONSE, das Attribut CONFIRMATION_KEY wurde nicht gesetzt."
          );
        }

        try {
          signin.setNickname(attr.getAsJsonPrimitive(SIGNIN.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(message, "SIGNIN | RESPONSE, das Attribut NICKNAME wurde nicht gesetzt.");
        }

        try {
          signin.setBackgroundColor(attr.getAsJsonPrimitive(SIGNIN.BACKGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut BACKGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "SIGNIN | RESPONSE, das Attribut BACKGROUND_COLOR wurde nicht gesetzt."
          );
        }

        try {
          signin.setForegroundColor(attr.getAsJsonPrimitive(SIGNIN.FOREGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut FOREGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "SIGNIN | RESPONSE, das Attribut FOREGROUND_COLOR wurde nicht gesetzt."
          );
        }

        try {
          signin.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(SIGNIN.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut MULTILINGUALKEY wurde nicht gesetzt.");
          throw new DecodeException(
              message, "SIGNIN | RESPONSE, das Attribut MULTILINGUALKEY wurde nicht gesetzt."
          );
        }
        try {
          signin.setText(attr.getAsJsonPrimitive(SIGNIN.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("SIGNIN | RESPONSE, das Attribut TEXT wurde nicht gesetzt.");
          throw new DecodeException(message, "SIGNIN | RESPONSE, das Attribut TEXT wurde nicht gesetzt.");

        }

        return signin;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeTOPICMEMBER(String message) throws DecodeException {
    TOPICMEMBER member = new TOPICMEMBER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonObject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonObject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonObject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.TOPICMEMBER.name().equals(command)) {
      member.setCommand(Command.TOPICMEMBER);
      if (REQUEST == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: TOPICMEMBER | REQUEST, das Attribut ROOM wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: TOPICMEMBER | REQUEST, das Attribut ROOM wurde nicht gesetzt."
          );
        }
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: TOPICMEMBER | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: TOPICMEMBER | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        return member;
      }
      else if (RESPONSE == header) {
        member.setHeader(header);
        member.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          member.setRoom(attr.getAsJsonPrimitive(MEMBER.ROOM).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: TOPICMEMBER | RESPONSE, das Attribut ROOM wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: TOPICMEMBER | RESPONSE, das Attribut ROOM wurde nicht gesetzt."
          );
        }
        try {
          member.setPseudoid(attr.getAsJsonPrimitive(MEMBER.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("Protokollfehler: TOPICMEMBER | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "Protokollfehler: TOPICMEMBER | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          member.setRoomtype(Roomtype.valueOf(attr.getAsJsonPrimitive(MEMBER.ROOMTYPE).getAsString()));
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Das Attribut ROOMTYPE wurde nicht definiert.");
        }
        // rooms decodieren
        JsonArray jsonarray = attr.getAsJsonArray(MEMBER.TOPICMEMBER);
        ChatUser singlemember[] = new ChatUser[jsonarray.size()];
        for (int index = 0; index < singlemember.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          singlemember[index] = new ChatUser();
          try {
            singlemember[index].setNickname(objectroom.getAsJsonPrimitive(ChatUser.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "Protokollfehler: TOPICMEMBER | RESPONSE | TOPICMEMBER, das Attribut NICKNAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "Protokollfehler: TOPICMEMBER | RESPONSE | TOPICMEMBER, das Attribut NICKNAME wurde nicht gesetzt."
            );
          }
        }
        member.setChatUser(singlemember);
        return member;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeTRANSFER(String message) throws DecodeException {
    TRANSFER transfer = new TRANSFER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.TRANSFER.name().equals(command)) {
      transfer.setCommand(Command.TRANSFER);
      if (REQUEST == header) {
        transfer.setHeader(header);
        transfer.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          transfer.setSlot(attr.getAsJsonPrimitive(TRANSFER.SLOT).getAsInt());
          transfer.setFilename(attr.getAsJsonPrimitive(TRANSFER.FILENAME).getAsString());
          transfer.setPathfile(attr.getAsJsonPrimitive(TRANSFER.PATHFILE).getAsString());
          transfer.setBlockindex(attr.getAsJsonPrimitive(TRANSFER.BLOCKINDEX).getAsInt());
          if (
            transfer.getBlockindex() < 0
          ) throw new DecodeException(
              message, "blockindex is negative, " + String.valueOf(transfer.getBlockindex())
          );
          transfer.setMaxDatablocks(attr.getAsJsonPrimitive(FILETRANSFER.MAXDATABLOCKS).getAsInt());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return transfer;
      }
      else if (RESPONSE == header) {
        transfer.setHeader(header);
        transfer.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          transfer.setSlot(attr.getAsJsonPrimitive(TRANSFER.SLOT).getAsInt());
          transfer.setFilename(attr.getAsJsonPrimitive(TRANSFER.FILENAME).getAsString());
          transfer.setPathfile(attr.getAsJsonPrimitive(TRANSFER.PATHFILE).getAsString());
          transfer.setBlockindex(attr.getAsJsonPrimitive(TRANSFER.BLOCKINDEX).getAsInt());
          if (
            transfer.getBlockindex() < 0
          ) throw new DecodeException(
              message, "blockindex is negative, " + String.valueOf(transfer.getBlockindex())
          );
          transfer.setEndflag(attr.getAsJsonPrimitive(TRANSFER.ENDFLAG).getAsBoolean());
          transfer.setPayload(attr.getAsJsonPrimitive(TRANSFER.PAYLOAD).getAsString());
          transfer.setMaxDatablocks(attr.getAsJsonPrimitive(FILETRANSFER.MAXDATABLOCKS).getAsInt());

        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return transfer;
      }
      else if (ERROR == header) {
        transfer.setHeader(header);
        transfer.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");
        try {
          transfer.setSlot(attr.getAsJsonPrimitive(TRANSFER.SLOT).getAsInt());
          transfer.setFilename(attr.getAsJsonPrimitive(TRANSFER.FILENAME).getAsString());
          transfer.setPathfile(attr.getAsJsonPrimitive(TRANSFER.PATHFILE).getAsString());
          transfer.setErrorMessage(attr.getAsJsonPrimitive(MESSAGE.ERRORMESSAGE).getAsString());
        }
        catch (NullPointerException e) {
          throw new DecodeException(message, "Ein Attribut wurde nicht definiert.");
        }
        return transfer;
      }
    }
    return new MESSAGE();
  }



  public MESSAGE decodeUPDATEFILETYPES(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.UPDATEFILETYPES.name().equals(command)) return new MESSAGE();
    UPDATEFILETYPES updatetypes = new UPDATEFILETYPES();
    updatetypes.setCommand(Command.UPDATEFILETYPES);
    updatetypes.setHeader(header);
    if (REQUEST == header) {
      updatetypes.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        updatetypes.setPseudoid(attr.get(FILETYPES.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal("Protokollfehler: UPDATEFILETYPES | REQUEST, das Attribut PSEUDOID wurde nicht definiert.");
        throw new DecodeException(
            message,
            "Protokollfehler: UPDATEFILETYPES | REQUEST, das Attribut PSEUDOID wurde nicht definiert."
        );
      }
      JsonArray jsonarray = null;
      try {
        jsonarray = attr.getAsJsonArray(FILETYPES.FILETYPES);
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut FILETYPES wurde nicht definiert.");
      }
      BlacklistTypes blacklist[] = new BlacklistTypes[jsonarray.size()];
      for (int index = 0; index < blacklist.length; index++) {
        JsonObject objectJson = jsonarray.get(index).getAsJsonObject();
        blacklist[index] = new BlacklistTypes();
        blacklist[index].setDescription(objectJson.get(BlacklistTypes.DESCRIPTION).getAsString());
        blacklist[index].setSuffix(objectJson.get(BlacklistTypes.SUFFIX).getAsString());
        blacklist[index].setChecked(objectJson.get(BlacklistTypes.CHECKED).getAsBoolean());
      }
      updatetypes.setFiletypes(blacklist);
    }
    else if (CONFIRM == header) {
      updatetypes.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        updatetypes.setPseudoid(attr.get(FILETYPES.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        log.fatal("Protokollfehler: UPDATEFILETYPES | CONFIRM, das Attribut PSEUDOID wurde nicht definiert.");
        throw new DecodeException(
            message,
            "Protokollfehler: UPDATEFILETYPES | CONFIRM, das Attribut PSEUDOID wurde nicht definiert."
        );
      }
    }
    return updatetypes;
  }



  MESSAGE decodeUPDATEPHONE(String message) throws DecodeException {
    UPDATEPHONE updatePhone = new UPDATEPHONE();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (!Command.UPDATEPHONE.name().equals(command)) return new MESSAGE();
    updatePhone.setCommand(Command.UPDATEPHONE);
    updatePhone.setHeader(header);
    if (REQUEST == header) {
      updatePhone.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        updatePhone.setPseudoid(attr.getAsJsonPrimitive(UPDATEPHONE.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut PSEUDOID wurde nicht definiert.");
      }
      try {
        updatePhone.setOnBusy(attr.getAsJsonPrimitive(UPDATEPHONE.ONBUSY).getAsBoolean());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut ONBUSY wurde nicht definiert.");
      }

    }
    else if (RESPONSE == header) {
      updatePhone.setDataset(Protocol.DATASET);
      JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
      try {
        updatePhone.setPseudoid(attr.getAsJsonPrimitive(UPDATEPHONE.PSEUDOID).getAsString());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut PSEUDOID wurde nicht definiert.");
      }
      try {
        updatePhone.setOnBusy(attr.getAsJsonPrimitive(UPDATEPHONE.ONBUSY).getAsBoolean());
      }
      catch (NullPointerException e) {
        throw new DecodeException(message, "Das Attribut ONBUSY wurde nicht definiert.");
      }
    }
    else if (ERROR == header) {

    }

    return updatePhone;
  }



  MESSAGE decodeUPDATEPORT(String message) throws DecodeException {
    UPDATEPORT updateport = new UPDATEPORT();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());

    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.UPDATEPORT.name().equals(command)) {
      updateport.setCommand(Command.UPDATEPORT);
      if (REQUEST == header) {
        updateport.setHeader(header);
        updateport.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");

        try {
          updateport.setPseudoid(attr.getAsJsonPrimitive(UPDATEPORT.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEPORT | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEPORT | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          updateport.setIp(attr.getAsJsonPrimitive(UPDATEPORT.IP).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEPORT | REQUEST, das Attribut IP wurde nicht gesetzt.");
          throw new DecodeException(message, "UPDATEPORT | REQUEST, das Attribut IP wurde nicht gesetzt.");
        }
        try {
          updateport.setPort(attr.getAsJsonPrimitive(UPDATEPORT.PORT).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEPORT | REQUEST, das Attribut PORT wurde nicht gesetzt.");
          throw new DecodeException(message, "UPDATEPORT | REQUEST, das Attribut PORT wurde nicht gesetzt.");
        }
        return updateport;
      }
      else if (RESPONSE == header) {
        updateport.setHeader(header);
        updateport.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt.");

        try {
          updateport.setPseudoid(attr.getAsJsonPrimitive(UPDATEPORT.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEPORT | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEPORT | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          updateport.setIp(attr.getAsJsonPrimitive(UPDATEPORT.IP).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEPORT | RESPONSE, das Attribut IP wurde nicht gesetzt.");
          throw new DecodeException(message, "UPDATEPORT | RESPONSE, das Attribut IP wurde nicht gesetzt.");
        }
        try {
          updateport.setPort(attr.getAsJsonPrimitive(UPDATEPORT.PORT).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEPORT | RESPONSE, das Attribut PORT wurde nicht gesetzt.");
          throw new DecodeException(message, "UPDATEPORT | RESPONSE, das Attribut PORT wurde nicht gesetzt.");
        }

        return updateport;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeUPDATEUSER(String message) throws DecodeException {
    UPDATEUSER updateuser = new UPDATEUSER();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.UPDATEUSER.name().equals(command)) {
      updateuser.setCommand(Command.UPDATEUSER);
      if (REQUEST == header) {
        updateuser.setHeader(header);
        updateuser.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) {
          log.fatal("UPDATEUSER | REQUEST, das Attribut DATASET wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | REQUEST, das Attribut DATASET wurde nicht gesetzt."
          );
        }

        try {
          updateuser.setIdentity(attr.getAsJsonPrimitive(UPDATEUSER.IDENTITY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | REQUEST, das Attribut IDENTITY wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | REQUEST, das Attribut IDENTITY wurde nicht gesetzt."
          );
        }

        try {
          updateuser.setBackgroundColor(attr.getAsJsonPrimitive(USER.BACKGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | REQUEST, das Attribut BACKGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | REQUEST, das Attribut BACKGROUND_COLOR wurde nicht gesetzt."
          );
        }
        try {
          updateuser.setForegroundColor(attr.getAsJsonPrimitive(USER.FOREGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | REQUEST, das Attribut FOREGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | REQUEST, das Attribut FOREGROUND_COLOR wurde nicht gesetzt."
          );
        }

        try {
          updateuser.setNickname(attr.getAsJsonPrimitive(USER.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | REQUEST, das Attribut NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | REQUEST, das Attribut NICKNAME wurde nicht gesetzt."
          );
        }
        return updateuser;
      }
      else if (CONFIRM == header) {
        updateuser.setHeader(header);
        updateuser.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) {
          log.fatal("UPDATEUSER | CONFIRM, das Attribut DATASET wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | CONFIRM, das Attribut DATASET wurde nicht gesetzt."
          );
        }

        try {
          updateuser.setIdentity(attr.getAsJsonPrimitive(UPDATEUSER.IDENTITY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | CONFIRM, das Attribut IDENTITY wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | CONFIRM, das Attribut IDENTITY wurde nicht gesetzt."
          );
        }

        try {
          updateuser.setBackgroundColor(attr.getAsJsonPrimitive(UPDATEUSER.BACKGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | CONFIRM, das Attribut BACKGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | CONFIRM, das Attribut BACKGROUND_COLOR wurde nicht gesetzt."
          );
        }
        try {
          updateuser.setForegroundColor(attr.getAsJsonPrimitive(UPDATEUSER.FOREGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | CONFIRM, das Attribut FOREGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | CONFIRM, das Attribut FOREGROUND_COLOR wurde nicht gesetzt."
          );
        }

        try {
          updateuser.setNickname(attr.getAsJsonPrimitive(UPDATEUSER.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | CONFIRM, das Attribut NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPDATEUSER | CONFIRM, das Attribut NICKNAME wurde nicht gesetzt."
          );
        }
        return updateuser;
      }
      else if (ERROR == header) {

        updateuser.setHeader(header);
        updateuser.setDataset(Protocol.DATASET);

        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) {
          log.fatal("UPDATEUSER | ERROR, das Attribut DATASET wurde nicht gesetzt.");
          throw new DecodeException(message, "UPDATEUSER | ERROR, das Attribut DATASET wurde nicht gesetzt.");
        }

        try {
          updateuser.setText(attr.getAsJsonPrimitive(UPDATEUSER.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPDATEUSER | ERROR, das Attribut TEXT wurde nicht gesetzt.");
          throw new DecodeException(message, "UPDATEUSER | ERROR, das Attribut TEXT wurde nicht gesetzt.");
        }

        return updateuser;
      }
    }
    return new MESSAGE();
  }



  MESSAGE decodeUPLOADFILES(String message) throws DecodeException {
    UPLOADFILES uploadfiles = new UPLOADFILES();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.UPLOADFILES.name().equals(command)) {
      uploadfiles.setCommand(Command.UPLOADFILES);
      if (REQUEST == header) {
        uploadfiles.setHeader(REQUEST);
        uploadfiles.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");

        try {
          uploadfiles.setPseudoid(attr.getAsJsonPrimitive(UPLOADFILES.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPLOADFILES | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt.");
          throw new DecodeException(
              message, "UPLOADFILES | REQUEST, das Attribut PSEUDOID wurde nicht gesetzt."
          );
        }
        try {
          uploadfiles.setIp(attr.getAsJsonPrimitive(UPLOADFILES.IP).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("UPLOADFILES | REQUEST, das Attribut IP wurde nicht gesetzt.");
          throw new DecodeException(message, "UPLOADFILES | REQUEST, das Attribut IP wurde nicht gesetzt.");
        }
        try {
          uploadfiles.setPort(attr.getAsJsonPrimitive(UPLOADFILES.PORT).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("UPLOADFILES | REQUEST, das Attribut PORT wurde nicht gesetzt.");
          throw new DecodeException(message, "UPLOADFILES | REQUEST, das Attribut PORT wurde nicht gesetzt.");
        }
        uploadfiles.setStarted(attr.getAsJsonPrimitive(UPLOADFILES.START).getAsBoolean());
        JsonArray jsonarray = attr.getAsJsonArray(UPLOADFILES.UPLOADFILES);
        Uploadfile uploadfile[] = new Uploadfile[jsonarray.size()];
        for (int index = 0; index < uploadfile.length; index++) {
          JsonObject objectfile = jsonarray.get(index).getAsJsonObject();
          uploadfile[index] = new Uploadfile();
          uploadfile[index].setFilename(objectfile.getAsJsonPrimitive(Uploadfile.FILENAME).getAsString());
          uploadfile[index].setFilesize(objectfile.getAsJsonPrimitive(Uploadfile.FILESIZE).getAsLong());

        }
        uploadfiles.setUploadfile(uploadfile);
        return uploadfiles;
      }
      else if (RESPONSE == header) {
        uploadfiles.setHeader(RESPONSE);
        uploadfiles.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        try {
          uploadfiles.setPseudoid(attr.getAsJsonPrimitive(UPLOADFILES.PSEUDOID).getAsString());
        }
        catch (NullPointerException e) {
//          log.fatal("UPLOADFILES | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt.");
//          throw new DecodeException(
//              message, "UPLOADFILES | RESPONSE, das Attribut PSEUDOID wurde nicht gesetzt."
//          );
        }
        try {
          uploadfiles.setIp(attr.getAsJsonPrimitive(UPLOADFILES.IP).getAsString());
        }
        catch (NullPointerException e) {
//          log.fatal("UPLOADFILES | RESPONSE, das Attribut IP wurde nicht gesetzt.");
//          throw new DecodeException(message, "UPLOADFILES | RESPONSE, das Attribut IP wurde nicht gesetzt.");
        }
        uploadfiles.setStarted(attr.getAsJsonPrimitive(UPLOADFILES.START).getAsBoolean());
        return uploadfiles;
      }
    }

    return new MESSAGE();
  }



  MESSAGE decodeUSERONLINELIST(String message) throws DecodeException {
    USERONLINELIST useronline = new USERONLINELIST();
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonobject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonobject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonobject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.USERONLINELIST.name().equals(command)) {
      if (RESPONSE == header) {
        useronline.setCommand(Command.USERONLINELIST);
        useronline.setHeader(RESPONSE);
        useronline.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) {
          log.fatal("USERONLINELIST | RESPONSE, das Attribut DATASET wurde nicht gesetzt.");
          throw new DecodeException(
              message, "USERONLINELIST | RESPONSE, das Attribut DATASET wurde nicht gesetzt."
          );
        }
        JsonArray jsonarray = attr.getAsJsonArray(USERONLINELIST.USERONLINELIST);
        UserOnline online[] = new UserOnline[jsonarray.size()];

        for (int index = 0; index < online.length; index++) {
          JsonObject objectroom = jsonarray.get(index).getAsJsonObject();
          online[index] = new UserOnline();
          try {
            online[index].setIp(objectroom.getAsJsonPrimitive(UserOnline.IP).getAsString());
          }
          catch (NullPointerException e) {}
          try {
            online[index].setNickname(objectroom.getAsJsonPrimitive(UserOnline.NICKNAME).getAsString());
          }
          catch (NullPointerException e) {
            log.fatal(
                "USERONLINELIST | RESPONSE | USERONLINELIST[], das Attribut NICKNAME wurde nicht gesetzt."
            );
            throw new DecodeException(
                message,
                "USERONLINELIST | RESPONSE | USERONLINELIST[], das Attribut NICKNAME wurde nicht gesetzt."
            );

          }
        }
        useronline.setUserOnline(online);
        return useronline;
      }
      else if (REQUEST == header) {
        useronline.setCommand(Command.USERONLINELIST);
        useronline.setHeader(REQUEST);
        useronline.setDataset(Protocol.DATASET);
        JsonObject attr = jsonobject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) throw new DecodeException(message, "Der Datensatz fehlt");
        return useronline;
      }
    }
    return new MESSAGE();
  }



  /**
   * 
   * @param message
   * @return
   * @throws DecodeException
   */
  MESSAGE decodeUSRLOGIN(String message) throws DecodeException {
    JsonElement jsonElement = JsonParser.parseString(message);
    if (!jsonElement.isJsonObject()) return new MESSAGE();
    JsonObject jsonObject = jsonElement.getAsJsonObject();
    HEADER header = HEADER.toHeader(jsonObject.getAsJsonPrimitive(Protocol.HEADER).getAsString());
    String command = jsonObject.getAsJsonPrimitive(Command.getCommandKey()).getAsString();
    if (Command.USRLOGIN.name().equals(command)) {
      if (REQUEST == header) {
        USRLOGIN userlogin = new USRLOGIN();
        userlogin.setHeader(header);
        userlogin.setCommand(Command.USRLOGIN);
        userlogin.setDataset(Protocol.DATASET);

        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);

        try {
          userlogin.setAgent(Agent.valueOf(attr.getAsJsonPrimitive(USRLOGIN.AGENT).getAsString()));
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | REQUEST, das Attribut AGENT wurde nicht gesetzt.");
          throw new DecodeException(message, "USRLOGIN | REQUEST, das Attribut AGENT wurde nicht gesetzt.");
        }

        try {
          userlogin.setIdentity(attr.getAsJsonPrimitive(USRLOGIN.IDENTITY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | REQUEST, das Attribut IDENTITY wurde nicht gesetzt.");
          throw new DecodeException(
              message, "USRLOGIN | REQUEST, das Attribut IDENTITY wurde nicht gesetzt."
          );

        }
        return userlogin;

      }
      else if (CONFIRM == header) {
        USRLOGIN usrlogin = new USRLOGIN();
        usrlogin.setHeader(header);
        usrlogin.setCommand(Command.USRLOGIN);
        usrlogin.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);

        try {
          usrlogin.setSession(attr.getAsJsonPrimitive(USRLOGIN.SESSION).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut SESSION wurde nicht gesetzt.");
          throw new DecodeException(message, "USRLOGIN | CONFIRM, das Attribut SESSION wurde nicht gesetzt.");
        }

        try {
          usrlogin.setIdentity(attr.getAsJsonPrimitive(USRLOGIN.IDENTITY).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut IDENTITY wurde nicht gesetzt.");
          throw new DecodeException(
              message, "USRLOGIN | CONFIRM, das Attribut IDENTITY wurde nicht gesetzt."
          );
        }

        try {
          usrlogin.setNickname(attr.getAsJsonPrimitive(USRLOGIN.NICKNAME).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut NICKNAME wurde nicht gesetzt.");
          throw new DecodeException(
              message, "USRLOGIN | CONFIRM, das Attribut NICKNAME wurde nicht gesetzt."
          );
        }

        try {
          usrlogin.setBackgroundColor(attr.getAsJsonPrimitive(USRLOGIN.BACKGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut BACKGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "USRLOGIN | CONFIRM, das Attribut BACKGROUND_COLOR wurde nicht gesetzt."
          );
        }

        try {
          usrlogin.setForegroundColor(attr.getAsJsonPrimitive(USRLOGIN.FOREGROUND_COLOR).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut FOREGROUND_COLOR wurde nicht gesetzt.");
          throw new DecodeException(
              message, "USRLOGIN | CONFIRM, das Attribut FOREGROUND_COLOR wurde nicht gesetzt."
          );
        }
        try {
          usrlogin.setVolume(attr.getAsJsonPrimitive(USRLOGIN.VOLUME).getAsInt());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut VOLUME wurde nicht gesetzt.");
          throw new DecodeException(message, "USRLOGIN | CONFIRM, das Attribut VOLUME wurde nicht gesetzt.");
        }
        try {
          usrlogin.setOncall(attr.getAsJsonPrimitive(USRLOGIN.ONCALL).getAsBoolean());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | CONFIRM, das Attribut ONCALL wurde nicht gesetzt.");
          throw new DecodeException(message, "USRLOGIN | CONFIRM, das Attribut ONCALL wurde nicht gesetzt.");
        }
        return usrlogin;
      }
      else if (ERROR == header) {
        USRLOGIN usrlogin = new USRLOGIN();
        usrlogin.setHeader(header);
        usrlogin.setCommand(Command.USRLOGIN);
        usrlogin.setDataset(Protocol.DATASET);
        JsonObject attr = jsonObject.getAsJsonObject(Protocol.DATASET);
        if (attr == null) {
          log.fatal("USRLOGIN | ERROR, das Attribut DATASET wurde nicht gesetzt.");
          throw new DecodeException(message, "USRLOGIN | ERROR, das Attribut DATASET wurde nicht gesetzt.");
        }
        try {
          usrlogin.setMultilingualkey(
              KEY.fromValue(attr.getAsJsonPrimitive(USRLOGIN.MULTILINGUALKEY).getAsString())
          );
        }
        catch (NullPointerException e) {}

        try {
          usrlogin.setText(attr.getAsJsonPrimitive(USRLOGIN.TEXT).getAsString());
        }
        catch (NullPointerException e) {
          log.fatal("USRLOGIN | ERROR, das Attribut TEXT wurde nicht gesetzt.");
          throw new DecodeException(message, "USRLOGIN | ERROR, das Attribut TEXT wurde nicht gesetzt.");
        }

        return usrlogin;
      }
    }
    return new MESSAGE();

  }



  @Override
  public void destroy() {

  }



  @Override
  public void init(EndpointConfig arg0) {
    // gson = new Gson();
  }



  @Override
  public boolean willDecode(String incoming) {
    return true;
  }

}
