/// <summary>
        /// Aktualisiert den Kanal unter Berücksichtigung der entsprechenden Subklassen-Attribute.
        /// Es wird abhängig vom Typ des Kanals die Kanal-Tabelle und die Tabellen für die Subklassen aktualisiert.
        /// </summary>
        /// <param name="channel">Das Objekt vom Typ Kanal oder vom Typ eines der Unterklassen.</param>
        /// <exception cref="DatabaseException">Wirft DatabaseException, wenn Aktualisierung des Kanals fehlschlägt.</exception>
        public void UpdateChannelWithSubclass(Channel channel)
        {
            if (channel == null)
            {
                Debug.WriteLine("No valid channel object passed to the StoreChannel method.");
                return;
            }

            // Frage das Mutex Objekt ab.
            Mutex mutex = DatabaseManager.GetDatabaseAccessMutexObject();

            // Fordere Zugriff auf die Datenbank an.
            if (mutex.WaitOne(DatabaseManager.MutexTimeoutValue))
            {
                using (SQLiteConnection conn = DatabaseManager.GetConnection())
                {
                    try
                    {
                        // Starte eine Transaktion.
                        using (var statement = conn.Prepare("BEGIN TRANSACTION"))
                        {
                            statement.Step();
                        }

                        // Setze Aktualisierungsquery für Kanal-Tabelle ab.
                        using (var updateChannelStmt = conn.Prepare("UPDATE Channel " +
                            "SET Name=?, Description=?, CreationDate=?, ModificationDate=?, " +
                            "Type=?, Term=?, Location=?, Dates=?, Contact=?, Website=?, Deleted=?, NotificationSettings_NotifierId=? " + 
                            "WHERE Id=?;"))
                        {
                            updateChannelStmt.Bind(1, channel.Name);
                            updateChannelStmt.Bind(2, channel.Description);
                            updateChannelStmt.Bind(3, DatabaseManager.DateTimeToSQLite(channel.CreationDate));
                            updateChannelStmt.Bind(4, DatabaseManager.DateTimeToSQLite(channel.ModificationDate));
                            updateChannelStmt.Bind(5, (int)channel.Type);
                            updateChannelStmt.Bind(6, channel.Term);
                            updateChannelStmt.Bind(7, channel.Locations);
                            updateChannelStmt.Bind(8, channel.Dates);
                            updateChannelStmt.Bind(9, channel.Contacts);
                            updateChannelStmt.Bind(10, channel.Website);
                            updateChannelStmt.Bind(11, (channel.Deleted) ? 1 : 0);
                            updateChannelStmt.Bind(12, (int)channel.AnnouncementNotificationSetting);

                            updateChannelStmt.Bind(13, channel.Id);

                            updateChannelStmt.Step();
                            Debug.WriteLine("Update channel with id {0}.", channel.Id);
                        }

                        // Aktualisiere auch Subklassen-Tabelle abhängig vom Typ des Kanals.
                        switch (channel.Type)
                        {
                            case DataModel.Enums.ChannelType.LECTURE:
                                Lecture lecture = (Lecture)channel;

                                // Aktualisierung von Vorlesungs-Tabelle.
                                using (var updateLectureStmt = conn.Prepare("UPDATE Lecture SET " +
                                    "StartDate=?, EndDate=?, Lecturer=?, Assistant=? " +
                                    "WHERE Channel_Id=?;"))
                                {
                                    updateLectureStmt.Bind(1, lecture.StartDate);
                                    updateLectureStmt.Bind(2, lecture.EndDate);
                                    updateLectureStmt.Bind(3, lecture.Lecturer);
                                    updateLectureStmt.Bind(4, lecture.Assistant);
                                    updateLectureStmt.Bind(5, channel.Id);

                                    updateLectureStmt.Step();
                                }

                                Debug.WriteLine("Updated lecture.");
                                break;
                            case DataModel.Enums.ChannelType.EVENT:
                                Event channelEvent = (Event)channel;

                                // Aktualisierung von Event-Tabelle.
                                using (var updateEventStmt = conn.Prepare("UPDATE Event SET Cost=?, Organizer=? " +
                                    "WHERE Channel_Id=?;"))
                                {
                                    updateEventStmt.Bind(1, channelEvent.Cost);
                                    updateEventStmt.Bind(2, channelEvent.Organizer);
                                    updateEventStmt.Bind(3, channel.Id);

                                    updateEventStmt.Step();
                                }

                                Debug.WriteLine("Updated event.");
                                break;
                            case DataModel.Enums.ChannelType.SPORTS:
                                Sports channelSports = (Sports)channel;

                                // Aktualisierung von Sports-Tabelle.
                                using (var updateSportsStmt = conn.Prepare("UPDATE Sports SET Cost=?, NumberOfParticipants=? " +
                                    "WHERE Channel_Id=?;"))
                                {
                                    updateSportsStmt.Bind(1, channelSports.Cost);
                                    updateSportsStmt.Bind(2, channelSports.NumberOfParticipants);
                                    updateSportsStmt.Bind(3, channel.Id);

                                    updateSportsStmt.Step();
                                }

                                Debug.WriteLine("Updated sports.");
                                break;
                            default:
                                Debug.WriteLine("There is no subclass for channel type OTHER and STUDENT_GROUP, so updating is already complete.");
                                break;
                        }

                        // Commit der Transaktion.
                        using (var statement = conn.Prepare("COMMIT TRANSACTION"))
                        {
                            statement.Step();
                        }
                    }
                    catch (SQLiteException sqlEx)
                    {
                        Debug.WriteLine("SQLiteException has occurred in UpdateChannelWithSubclass. The message is: {0}." + sqlEx.Message);
                        // Rollback der Transaktion.
                        using (var statement = conn.Prepare("ROLLBACK TRANSACTION"))
                        {
                            statement.Step();
                        }
                        throw new DatabaseException("Update of the channel with id " + channel.Id + " has failed.");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Exception has occurred in UpdateChannelWithSubclass. The message is: {0}, " +
                            "and the stack trace is: {1}.", ex.Message, ex.StackTrace);
                        // Rollback der Transaktion.
                        using (var statement = conn.Prepare("ROLLBACK TRANSACTION"))
                        {
                            statement.Step();
                        }
                        throw new DatabaseException("Update of channel has failed.");
                    }
                    finally
                    {
                        mutex.ReleaseMutex();
                    }
                }   // Ende using Block.
            }
            else
            {
                Debug.WriteLine("Couldn't get access to database. Time out.");
                throw new DatabaseException("Could not get access to the database.");
            }       
        }
        /// <summary>
        /// Hilfsmethode, die aus einem durch eine Query zurückgelieferten Statement ein Objekt des Typs Kanal extrahiert.
        /// Je nach Typ des Kanals werden zusätzliche Informationen aus Subklassen-Tabellen abgefragt und ein Objekt
        /// der Subklasse extrahiert.
        /// </summary>
        /// <param name="conn">Eine aktive Connection zur Datenbank, um Informationen aus Subklassen-Tabellen abfragen zu können.</param>
        /// <param name="stmt">Das Statement, aus dem die Informationen extrahiert werden sollen.</param>
        /// <returns>Ein Objekt vom Typ Channel.</returns>
        private Channel retrieveChannelObjectFromStatement(SQLiteConnection conn, ISQLiteStatement stmt)
        {
            // Channel Objekt.
            Channel channel = null;

            try
            {
                // Initialisierung der Variablen.
                int id;
                string name, description, term, location, dates, contact, website, startDate, endDate, lecturer,
                    assistant, cost, organizer, participants;
                bool deleted;
                ChannelType type;
                Faculty faculty;
                NotificationSetting announcementNotificationSetting;
                DateTimeOffset creationDate, modificationDate;

                // Frage Kanal-Werte ab.
                id = Convert.ToInt32(stmt["Id"]);
                name = (string)stmt["Name"];
                description = (string)stmt["Description"];
                type = (ChannelType)Enum.ToObject(typeof(ChannelType), stmt["Type"]);
                creationDate = DatabaseManager.DateTimeFromSQLite(stmt["CreationDate"].ToString());
                modificationDate = DatabaseManager.DateTimeFromSQLite(stmt["ModificationDate"].ToString());
                term = (string)stmt["Term"];
                location = (string)stmt["Location"];
                dates = (string)stmt["Dates"];
                contact = (string)stmt["Contact"];
                website = (string)stmt["Website"];
                deleted = ((long)stmt["Deleted"] == 1) ? true : false;
                announcementNotificationSetting = (NotificationSetting)Enum.ToObject(typeof(NotificationSetting), stmt["NotificationSettings_NotifierId"]);

                // Falls notwendig, hole Daten aus Tabelle der Subklasse.
                switch (type)
                {
                    case ChannelType.LECTURE:
                        using (var getLectureStmt = conn.Prepare("SELECT * FROM Lecture WHERE Channel_Id=?;"))
                        {
                            getLectureStmt.Bind(1, id);

                            // Hole Ergebnis der Query.
                            if (getLectureStmt.Step() == SQLiteResult.ROW)
                            {
                                faculty = (Faculty)Enum.ToObject(typeof(Faculty), getLectureStmt["Faculty"]);
                                startDate = (string)getLectureStmt["StartDate"];
                                endDate = (string)getLectureStmt["EndDate"];
                                lecturer = (string)getLectureStmt["Lecturer"];
                                assistant = (string)getLectureStmt["Assistant"];

                                // Erstelle Lecture Objekt und füge es der Liste hinzu.
                                Lecture lecture = new Lecture(id, name, description, type, creationDate, modificationDate, term, location,
                                    dates, contact, website, deleted, faculty, startDate, endDate, lecturer, assistant);
                                channel = lecture;
                            }
                        }
                        break;
                    case ChannelType.EVENT:
                        using (var getEventStmt = conn.Prepare("SELECT * FROM Event WHERE Channel_Id=?;"))
                        {
                            getEventStmt.Bind(1, id);

                            // Hole Ergebnis der Query.
                            if (getEventStmt.Step() == SQLiteResult.ROW)
                            {
                                cost = (string)getEventStmt["Cost"];
                                organizer = (string)getEventStmt["Organizer"];

                                // Erstelle Event Objekt und füge es der Liste hinzu.
                                Event eventObj = new Event(id, name, description, type, creationDate, modificationDate, term, location,
                                    dates, contact, website, deleted, cost, organizer);
                                channel = eventObj;
                            }
                        }
                        break;
                    case ChannelType.SPORTS:
                        using (var getSportsStmt = conn.Prepare("SELECT * FROM Sports WHERE Channel_Id=?;"))
                        {
                            getSportsStmt.Bind(1, id);

                            // Hole Ergebnis der Query.
                            if (getSportsStmt.Step() == SQLiteResult.ROW)
                            {
                                cost = (string)getSportsStmt["Cost"];
                                participants = (string)getSportsStmt["NumberOfParticipants"];

                                // Erstelle Sports Objekt und füge es der Liste hinzu.
                                Sports sportsObj = new Sports(id, name, description, type, creationDate, modificationDate, term, location,
                                    dates, contact, website, deleted, cost, participants);
                                channel = sportsObj;
                            }
                        }
                        break;
                    default:
                        // Keine Subklasse, also erzeuge Kanal Objekt.
                        channel = new Channel(id, name, description, type, creationDate, modificationDate, term, location,
                            dates, contact, website, deleted);
                        break;
                }

                // Füge announcementNotificationSetting Einstellung noch dem Objekt hinzu.
                channel.AnnouncementNotificationSetting = announcementNotificationSetting;
            }
            catch(SQLiteException sqlEx){
                Debug.WriteLine("SQLiteException has occurred in retrieveChannelObjectFromStatement. The message is: {0}.", sqlEx.Message);
                throw new DatabaseException("Retrieve channel has failed.");
            }
            catch(Exception ex)
            {
                Debug.WriteLine("Exception has occurred in retrieveChannelObjectFromStatement. The message is: {0}, " +
                    "and the stack trace: {1}.", ex.Message, ex.StackTrace);
                throw new DatabaseException("Retrieve channel has failed.");
            }
            
            return channel;
        }
        /// <summary>
        /// Aktualisiere den Kanal. Bei dieser Methode werden nur die Kanalattribute in der Datenbank
        /// aktualisiert. Mögliche Attribute von Subklassen der Kanal Klasse werden ignoriert.
        /// </summary>
        /// <param name="channel">Eine Objektinstanz von Kanal mit den aktualisierten Daten für den Kanal.</param>
        /// <exception cref="DatabaseException">Wirft DatabaseException, wenn Aktualisierung des Kanals fehlschlägt.</exception>
        public void UpdateChannel(Channel channel)
        {
            if (channel == null)
            {
                Debug.WriteLine("No valid channel object passed to the UpdateChannel method.");
                return;
            }

            // Frage das Mutex Objekt ab.
            Mutex mutex = DatabaseManager.GetDatabaseAccessMutexObject();

            // Fordere Zugriff auf die Datenbank an.
            if (mutex.WaitOne(DatabaseManager.MutexTimeoutValue))
            {
                using (SQLiteConnection conn = DatabaseManager.GetConnection())
                {
                    try
                    {
                        // Aktualisiere Daten in Kanal-Tabelle.
                        using (var updateChannelStmt = conn.Prepare("UPDATE Channel SET Name=?, Description=?, " +
                            "CreationDate=?, ModificationDate=?, Type=?, Term=?, Location=?, Dates=?, Contact=?, " + 
                            "Website=?, Deleted=?, NotificationSettings_NotifierId=? " +
                            "WHERE Id=?;"))
                        {
                            updateChannelStmt.Bind(1, channel.Name);
                            updateChannelStmt.Bind(2, channel.Description);
                            updateChannelStmt.Bind(3, DatabaseManager.DateTimeToSQLite(channel.CreationDate));
                            updateChannelStmt.Bind(4, DatabaseManager.DateTimeToSQLite(channel.ModificationDate));
                            updateChannelStmt.Bind(5, (int)channel.Type);
                            updateChannelStmt.Bind(6, channel.Term);
                            updateChannelStmt.Bind(7, channel.Locations);
                            updateChannelStmt.Bind(8, channel.Dates);
                            updateChannelStmt.Bind(9, channel.Contacts);
                            updateChannelStmt.Bind(10, channel.Website);
                            updateChannelStmt.Bind(11, (channel.Deleted) ? 1 : 0);
                            updateChannelStmt.Bind(12, (int)channel.AnnouncementNotificationSetting);

                            updateChannelStmt.Bind(13, channel.Id);

                            updateChannelStmt.Step();

                            Debug.WriteLine("Update channel with id {0}.", channel.Id);
                        }
                    }
                    catch (SQLiteException sqlEx)
                    {
                        Debug.WriteLine("SQLiteException has occurred in UpdateChannel. The message is: {0}." + sqlEx.Message);
                        throw new DatabaseException("Update of the channel with id " + channel.Id + " has failed.");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Exception has occurred in UpdateChannel. The message is: {0}, " +
                            "and the stack trace is: {1}.", ex.Message, ex.StackTrace);
                        throw new DatabaseException("Update of channel has failed.");
                    }
                    finally
                    {
                        mutex.ReleaseMutex();
                    }
                }   // Ende using Block.
            }
            else
            {
                Debug.WriteLine("Couldn't get access to database. Time out.");
                throw new DatabaseException("Could not get access to the database.");
            }              
        }
 /// <summary>
 /// Aktualisiert die für die View relevanten Properties des im ViewModel verwalteten Kanals.
 /// </summary>
 /// <param name="currentChannel">Der aktuell im ViewModel verwaltete Kanal.</param>
 /// <param name="newChannel">Der Kanal mit den aktualisierten Daten.</param>
 private void updateViewRelatedPropeties(Channel currentChannel, Channel newChannel)
 {
     currentChannel.Name = newChannel.Name;
     currentChannel.Term = newChannel.Term;
 }
        /// <summary>
        /// Speichere einen Kanal in der lokalen Datenbank. 
        /// </summary>
        /// <param name="channel">Das Kanal Objekt mit den Daten des Kanals.</param>
        /// <exception cref="DatabaseException">Wirft DatabaseException, wenn die Kanaldaten nicht in der DB gespeichert werden konnten.</exception>
        public void StoreChannel(Channel channel)
        {
            if(channel == null)
            {
                Debug.WriteLine("No valid channel object passed to the StoreChannel method.");
                return;
            }

            // Frage das Mutex Objekt ab.
            Mutex mutex = DatabaseManager.GetDatabaseAccessMutexObject();

            // Fordere Zugriff auf die Datenbank an.
            if (mutex.WaitOne(DatabaseManager.MutexTimeoutValue))
            {
                using (SQLiteConnection conn = DatabaseManager.GetConnection())
                {
                    try
                    {
                        // Starte eine Transaktion.
                        using (var statement = conn.Prepare("BEGIN TRANSACTION"))
                        {
                            statement.Step();
                        }

                        // Speichere Kanaldaten.
                        using (var insertStmt = conn.Prepare("INSERT INTO Channel (Id, Name, Description, " +
                            "CreationDate, ModificationDate, Type, Term, Location, Dates, Contact, Website, Deleted, NotificationSettings_NotifierId) " +
                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"))
                        {
                            insertStmt.Bind(1, channel.Id);
                            insertStmt.Bind(2, channel.Name);
                            insertStmt.Bind(3, channel.Description);
                            insertStmt.Bind(4, DatabaseManager.DateTimeToSQLite(channel.CreationDate));
                            insertStmt.Bind(5, DatabaseManager.DateTimeToSQLite(channel.ModificationDate));
                            insertStmt.Bind(6, (int)channel.Type);
                            insertStmt.Bind(7, channel.Term);
                            insertStmt.Bind(8, channel.Locations);
                            insertStmt.Bind(9, channel.Dates);
                            insertStmt.Bind(10, channel.Contacts);
                            insertStmt.Bind(11, channel.Website);
                            insertStmt.Bind(12, (channel.Deleted) ? 1 : 0);

                            // Channel hat zu Begin immer Default Benachrichtigungseinstellungen.
                            channel.AnnouncementNotificationSetting = NotificationSetting.APPLICATION_DEFAULT;
                            insertStmt.Bind(13, (int)channel.AnnouncementNotificationSetting);

                            insertStmt.Step();
                        }

                        // Speichere Subklassen Parameter abhängig vom Typ des Kanals.
                        switch (channel.Type)
                        {
                            case DataModel.Enums.ChannelType.LECTURE:
                                Lecture lecture = (Lecture)channel;

                                // Speichere Vorlesungsdaten.
                                using (var insertLectureStmt = conn.Prepare("INSERT INTO Lecture (Channel_Id, " +
                                    "Faculty, StartDate, EndDate, Lecturer, Assistant) " +
                                    "VALUES (?, ?, ?, ?, ?, ?);"))
                                {
                                    insertLectureStmt.Bind(1, channel.Id);
                                    insertLectureStmt.Bind(2, (int)lecture.Faculty);
                                    insertLectureStmt.Bind(3, lecture.StartDate);
                                    insertLectureStmt.Bind(4, lecture.EndDate);
                                    insertLectureStmt.Bind(5, lecture.Lecturer);
                                    insertLectureStmt.Bind(6, lecture.Assistant);

                                    insertLectureStmt.Step();
                                }

                                Debug.WriteLine("Stored lecture channel.");
                                break;
                            case DataModel.Enums.ChannelType.EVENT:
                                Event eventChannel = (Event)channel;

                                // Speichere Eventdaten.
                                using (var insertEventStmt = conn.Prepare("INSERT INTO Event (Channel_Id, Cost, Organizer) " +
                                    "VALUES (?, ?, ?);"))
                                {
                                    insertEventStmt.Bind(1, channel.Id);
                                    insertEventStmt.Bind(2, eventChannel.Cost);
                                    insertEventStmt.Bind(3, eventChannel.Organizer);

                                    insertEventStmt.Step();
                                }

                                Debug.WriteLine("Stored event channel.");
                                break;
                            case DataModel.Enums.ChannelType.SPORTS:
                                Sports sportsChannel = (Sports)channel;

                                // Speichere Sportgruppendaten.
                                using (var insertSportsStmt = conn.Prepare("INSERT INTO Sports (Channel_Id, Cost, NumberOfParticipants) " +
                                    "VALUES (?, ?, ?);"))
                                {
                                    insertSportsStmt.Bind(1, channel.Id);
                                    insertSportsStmt.Bind(2, sportsChannel.Cost);
                                    insertSportsStmt.Bind(3, sportsChannel.NumberOfParticipants);

                                    insertSportsStmt.Step();
                                }

                                Debug.WriteLine("Stored sports channel.");
                                break;
                            default:
                                Debug.WriteLine("There is no subclass for channel type OTHER and STUDENT_GROUP, so storing is already complete.");
                                break;
                        }

                        // Commit der Transaktion.
                        using (var statement = conn.Prepare("COMMIT TRANSACTION"))
                        {
                            statement.Step();
                        }
                    }
                    catch (SQLiteException sqlEx)
                    {
                        Debug.WriteLine("SQLiteException has occurred in StoreChannel. Exception message is: {0}.", sqlEx.Message);
                        // Rollback der Transaktion.
                        using (var statement = conn.Prepare("ROLLBACK TRANSACTION"))
                        {
                            statement.Step();
                        }

                        throw new DatabaseException("Storing channel data in database has failed.");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Exception has occurred in StoreChannel. " +
                            "Exception message is: {0}, and stack trace is {1}.", ex.Message, ex.StackTrace);
                        // Rollback der Transaktion.
                        using (var statement = conn.Prepare("ROLLBACK TRANSACTION"))
                        {
                            statement.Step();
                        }

                        throw new DatabaseException("Storing channel data in database has failed.");
                    }
                    finally
                    {
                        mutex.ReleaseMutex();
                    }
                }    // Ende using block.
            }
            else
            {
                Debug.WriteLine("Couldn't get access to database. Time out.");
                throw new DatabaseException("Could not get access to the database.");
            }               
        }
        /// <summary>
        /// Aktualisiert die für die View relevanten Properties eines aktuell vom ViewModel gehaltenen
        /// Kanal-Objekts.
        /// </summary>
        /// <param name="currentChannel">Das aktuell vom ViewModel gehaltene Channel-Objekt.</param>
        /// <param name="newChannel">Das Channel-Objekt mit den aktualisierten Daten.</param>
        private void updateViewRelatedChannelProperties(Channel currentChannel, Channel newChannel)
        {
            currentChannel.Name = newChannel.Name;
            currentChannel.Description = newChannel.Description;
            currentChannel.Term = newChannel.Term;
            currentChannel.CreationDate = newChannel.CreationDate;
            currentChannel.ModificationDate = newChannel.ModificationDate;
            currentChannel.Locations = newChannel.Locations;
            currentChannel.Dates = newChannel.Dates;
            currentChannel.Contacts = newChannel.Contacts;
            currentChannel.Website = newChannel.Website;

            switch (currentChannel.Type)
            {

                case ChannelType.LECTURE:
                    Lecture currentLecture = currentChannel as Lecture;
                    Lecture newLecture = newChannel as Lecture;
                    currentLecture.StartDate = newLecture.StartDate;
                    currentLecture.EndDate = newLecture.EndDate;
                    currentLecture.Lecturer = newLecture.Lecturer;
                    currentLecture.Assistant = newLecture.Assistant;
                    break;
                case ChannelType.EVENT:
                    Event currentEvent = currentChannel as Event;
                    Event newEvent = newChannel as Event;
                    currentEvent.Cost = newEvent.Cost;
                    currentEvent.Organizer = newEvent.Organizer;
                    break;
                case ChannelType.SPORTS:
                    Sports currentSportsObj = currentChannel as Sports;
                    Sports newSportsObj = newChannel as Sports;
                    currentSportsObj.Cost = newSportsObj.Cost;
                    currentSportsObj.NumberOfParticipants = newSportsObj.NumberOfParticipants;
                    break;
            }
        }
 /// <summary>
 /// Hilfsmethode, welche die Validierung der Properties eines Kanalobjekts ausführt.
 /// Die Properties werden unter Berücksichtigung des Typs des Kanals und möglicher 
 /// Properties entsprechender Subklassen ausgeführt. Falls Validierungsfehler auftreten,
 /// werden die über die Report-Schnittstelle an das ViewModel gemeldet.
 /// </summary>
 /// <param name="channel">Das Kanalobjekt, das validiert werden soll.</param>
 /// <returns>Liefert true, wenn keine Validierungsfehler aufgetreten sind, liefert false bei Validierungsfehlern.</returns>
 private bool validateChannelProperties(Channel channel)
 {
     switch (channel.Type)
     {
         case ChannelType.LECTURE:
             Lecture lecture = channel as Lecture;
             if (lecture != null)
             {
                 lecture.ClearValidationErrors();
                 lecture.ValidateAll();
             }
             if (lecture.HasValidationErrors())
             {
                 reportValidationErrors(lecture.GetValidationErrors());
                 return false;
             }
             break;
         case ChannelType.EVENT:
             Event eventObj = channel as Event;
             if (eventObj != null)
             {
                 eventObj.ClearValidationErrors();
                 eventObj.ValidateAll();
             }
             if (eventObj.HasValidationErrors())
             {
                 reportValidationErrors(eventObj.GetValidationErrors());
                 return false;
             }
             break;
         case ChannelType.SPORTS:
             Sports sportObj = channel as Sports;
             if (sportObj != null)
             {
                 sportObj.ClearValidationErrors();
                 sportObj.ValidateAll();
             }
             if (sportObj.HasValidationErrors())
             {
                 reportValidationErrors(sportObj.GetValidationErrors());
                 return false;
             }
             break;
         default:
             channel.ClearValidationErrors();
             channel.ValidateAll();
             if (channel.HasValidationErrors())
             {
                 reportValidationErrors(channel.GetValidationErrors());
                 return false;
             }
             break;
     }
     return true;
 }
 /// <summary>
 /// Fügt einen Kanal den lokal verwalteten Kanaldatensätzen hinzu.
 /// </summary>
 /// <param name="newChannel">Der hinzuzufügende Kanal.</param>
 /// <exception cref="ClientException">Wirft ClientException, wenn Hinzufügen fehlschlägt.</exception>
 public void AddToLocalChannels(Channel newChannel)
 {
     try
     {
         channelDatabaseManager.StoreChannel(newChannel);
     }
     catch (DatabaseException ex)
     {
         Debug.WriteLine("Couldn't store channel.");
         throw new ClientException(ErrorCodes.LocalDatabaseException, ex.Message);
     }
 }
        /// <summary>
        /// Legt einen neuen Kanal an. Die Daten des Kanals werden in Form eines
        /// Channel Objekts übergeben. Es wird ein Request an den Server übermittelt, um
        /// auf dem Server eine neue Kanalressource anzulegen.
        /// </summary>
        /// <param name="newChannel">Die Daten des neu anzulegenden Kanals in Form eines Objekts der Channel Klasse.</param>
        /// <returns>Liefert true, wenn der Kanal erfolgreich angelegt wurde, ansonsten false.</returns>
        /// <exception cref="ClientException">Wirft eine ClientException, wenn ein Fehler während des Erstellungsvorgangs auftritt.</exception>
        public async Task<bool> CreateChannelAsync(Channel newChannel)
        {
            if (newChannel == null)
                return false;

            Moderator activeModerator = GetLocalModerator();
            if (activeModerator == null)
                return false;

            // Führe Validierung der Kanaldaten durch. Abbruch bei aufgetretenen Validierungsfehlern.
            clearValidationErrors();
            bool validationSuccessful = validateChannelProperties(newChannel);

            // Breche ab, wenn Validierungsfehler aufgetreten sind.
            if (!validationSuccessful)
                return false;

            // Generiere JSON-Dokument aus Objekt.
            string jsonContent = jsonParser.ParseChannelToJsonString(newChannel);
            if (jsonContent == null)
            {
                Debug.WriteLine("Error during serialization from channel object to json string. Could " + 
                    "not create a channel. Execution is aborted.");
                return false;
            }

            string serverResponse = null;
            try
            {
                // Setzte Request zum Anlegen eines Kanals ab.
                serverResponse = await channelApi.SendCreateChannelRequestAsync(
                    activeModerator.ServerAccessToken,
                    jsonContent);
            }
            catch (APIException ex)
            {
                // Bilde ab auf ClientException.
                throw new ClientException(ex.ErrorCode, "Server rejected create channel request.");
            }

            // Extrahiere erhaltene Channel Resource aus JSON-Dokument.
            Channel createdChannel = jsonParser.ParseChannelFromJson(serverResponse);
            if (createdChannel != null)
            {
                try
                {
                    // Speichere Kanal lokal ab.
                    channelDatabaseManager.StoreChannel(createdChannel);

                    // Füge den Moderator als verwantwortlichen Moderator hinzu.
                    channelDatabaseManager.AddModeratorToChannel(
                        createdChannel.Id,
                        activeModerator.Id,
                        true);
                }
                catch (DatabaseException ex)
                {
                    Debug.WriteLine("Database Exception, message is: {0}.", ex.Message);
                    // Bilde ab auf ClientException.
                    throw new ClientException(ErrorCodes.LocalDatabaseException, "Storing process of " +
                        "created channel object in local DB has failed");
                }
            }
            else
            {
                throw new ClientException(ErrorCodes.JsonParserError, "Parsing of server response has failed.");
            }

            return true;
        }
 /// <summary>
 /// Ersetzt die lokal verwaltete Version des Kanals durch eine neue
 /// Version desselben Kanals.
 /// </summary>
 /// <param name="newChannel">Die neue Version des Kanals.</param>
 ///<exception cref="ClientException">Wirft ClientException, wenn Aktion aufgrund eines 
 ///     Fehlers nicht ausgeführt werden kann.</exception>
 public void ReplaceLocalChannel(Channel newChannel)
 {
     try
     {
         channelDatabaseManager.UpdateChannelWithSubclass(newChannel);
     }
     catch (DatabaseException ex)
     {
         Debug.WriteLine("Couldn't perform the replace local channel functionality.");
         throw new ClientException(ErrorCodes.LocalDatabaseException, ex.Message);
     }
 }
        /// <summary>
        /// Ersetzt einen lokalen Kanal unter Beibehaltung der vom Nutzer eingestellten Anwendungseinstellungen.
        /// </summary>
        /// <param name="newChannel">Die neue Kanalressource, welche die alte Ressource lokal ersetzt.</param>
        public void ReplaceLocalChannelWhileKeepingNotificationSettings(Channel newChannel)
        {
            try
            {
                Channel oldChannel = channelDatabaseManager.GetChannel(newChannel.Id);

                // Übernehme NotificationSettings von lokalem Kanal.
                newChannel.AnnouncementNotificationSetting = oldChannel.AnnouncementNotificationSetting;
                // Ersetze lokalen Datensatz durch neuen Datensatz.
                ReplaceLocalChannel(newChannel);
            }
            catch (DatabaseException ex)
            {
                Debug.WriteLine("ReplaceLocalChannelWhileKeepingNotificationSettings: Error occurred!");
                throw new ClientException(ErrorCodes.LocalDatabaseException, ex.Message);
            }
        }
        /// <summary>
        /// Prüft, ob alle Beziehungen zwischen Kanalressourcen und dem aktuell eingeloggten
        /// Moderator aktuell sind und aktualisiert diese falls notwendig. 
        /// </summary>
        /// <param name="managedChannels">Liste von aktuell verwalteten Kanälen des Moderators.</param>
        /// <exception cref="ClientException">Wirft ClientException, wenn Aktualisierung fehlschlägt.</exception>
        //public void UpdateManagedChannelsRelationships(List<Channel> managedChannels)
        //{
        //    Moderator activeModerator = GetLocalModerator();
        //    if (activeModerator == null)
        //        return;

        //    try
        //    {
        //        // Prüfe, ob der aktuell eingeloggte Moderator schon in der Datenbank enthalten ist.
        //        if (!moderatorDatabaseManager.IsModeratorStored(activeModerator.Id))
        //        {
        //            Debug.WriteLine("Need to store the moderator with id {0} in local DB.", activeModerator.Id);
        //            moderatorDatabaseManager.StoreModerator(activeModerator);
        //        }

        //        // Prüfe, ob Moderator auch lokal als Verantwortlicher für Kanäle eingetragen ist.
        //        foreach (Channel channel in managedChannels)
        //        {
        //            if (!channelDatabaseManager.IsResponsibleForChannel(channel.Id, activeModerator.Id))
        //            {
        //                // Kanal gefunden, der vorher noch nicht von diesem Moderator verwaltet wurde.
        //                // Trage Moderator ein.
        //                Debug.WriteLine("Need to add the moderator with id {0} as a responsible moderator " +
        //                    "for the channel with id {1}.", activeModerator.Id, channel.Id);
        //                channelDatabaseManager.AddModeratorToChannel(channel.Id, activeModerator.Id, true);

        //                // Stoße das Herunterladen der für den neu hinzugekommenen Kanal relevanten Daten an.
        //                // Bemerkung: Falls das fehlschlägt wird kein Fehler geworfen. Die Daten können auch im Fehlerfall später nachgeladen werden.
        //                Task.Run(() => retrieveAndStoreManagedChannelInfoAsync(activeModerator, channel.Id));
        //            }
        //        }

        //        // Frage verwaltete Kanäle aus der DB ab.
        //        List<Channel> managedChannelsFromDB = channelDatabaseManager.GetManagedChannels(activeModerator.Id);
        //        // Prüfe, ob es darin noch einen Kanal gibt, der nicht mehr in der aktuellen Liste von Kanälen steht.
        //        for (int i = 0; i < managedChannelsFromDB.Count; i++)
        //        {
        //            bool isContained = false;

        //            foreach (Channel channel in managedChannels)
        //            {
        //                if (channel.Id == managedChannelsFromDB[i].Id)
        //                {
        //                    isContained = true;
        //                }
        //            }

        //            if (!isContained)
        //            {
        //                RemoveChannelFromManagedChannels(activeModerator, managedChannelsFromDB[i]);
        //            }
        //        }

        //    }
        //    catch (DatabaseException ex)
        //    {
        //        Debug.WriteLine("Database exception occurred in UpdateManagedChannelsRelationships. Msg is {0}.", ex.Message);
        //        throw new ClientException(ErrorCodes.LocalDatabaseException, "Failed to update managed channels relationships.");
        //    }
        //}

        /// <summary>
        /// Nimmt einen Kanal aus der Liste der verwalteten Kanäle raus und räumt
        /// mit diesem Kanal in Verbindung stehende Ressourcen weg, die dann nicht mehr
        /// benötigt werden. 
        /// </summary>
        /// <param name="activeModerator">Der gerade aktive Moderator, für den der Kanal aus der Liste der
        ///     verwalteten Kanäle ausgetragen wird.</param>
        /// <param name="channel">Der Kanal, der aus der Liste genommen wird.</param>
        public void RemoveChannelFromManagedChannels(Moderator activeModerator, Channel channel)
        {
            try
            {
                // Setzte Verantwortlichkeit auf inaktiv für diesen Kanal.
                Debug.WriteLine("Need to set moderator isActive to false for channel with id {0}.", channel.Id);
                channelDatabaseManager.AddModeratorToChannel(
                    channel.Id,
                    activeModerator.Id,
                    false);

                // Prüfe, ob der Kanal abonniert ist.
                bool isSubscribed = channelDatabaseManager.IsChannelSubscribed(channel.Id);
                if (!isSubscribed)
                {
                    // Kanal nicht noch vom lokalen Nutzer abonniert. Lösche Announcements und Moderator-Info.
                    Debug.WriteLine("Channel with id {0} not subscribed. Delete announcements and moderator info.", channel.Id);
                    channelDatabaseManager.DeleteAllAnnouncementsOfChannel(channel.Id);
                    channelDatabaseManager.RemoveAllModeratorsFromChannel(channel.Id);
                }

                // Lösche in jedem Fall die Reminder.
                Debug.WriteLine("Deleting reminders for channel with id {0}.", channel.Id);
                channelDatabaseManager.DeleteRemindersForChannel(channel.Id);
            }
            catch (DatabaseException ex)
            {
                // Keine weitere Aktion, da diese Funktionalität im Hintergrund abläuft und
                // nicht vom Nutzer aktiv ausgelöst wird.
                Debug.WriteLine("Error during removal of managed channel. No further action is taken." + 
                    "Error message is: {0}.", ex.Message);
            }
        }
        /// <summary>
        /// Fügt den übergebenen Kanal der Liste der verwalteten Kanäle hinzu für den übergebenen
        /// Moderator. Trägt dabei den übergebenen Moderator als Verantwortlichen für den übergebenen Kanal
        /// ein und schaut ob der lokale Datensatz des Kanals hinzugefügt oder aktualisiert werden muss. 
        /// </summary>
        /// <param name="moderator">Der Moderator, für den der Kanal zur Liste der verwalteten Kanäle hinzukommt.</param>
        /// <param name="newManagedChannel">Der hinzuzufügende Kanal.</param>
        public void AddChannelToLocalManagedChannels(Moderator moderator, Channel newManagedChannel)
        {
            if (moderator == null || newManagedChannel == null)
                return;

            try
            {
                // Prüfe, ob der aktuell eingeloggte Moderator schon in der Datenbank enthalten ist.
                // Falls nicht, speichere ihn ab.
                if (!moderatorDatabaseManager.IsModeratorStored(moderator.Id))
                {
                    Debug.WriteLine("SynchronizeLocalManagedChannels: Need to store the moderator with id {0} in local DB.",
                        moderator.Id);
                    moderatorDatabaseManager.StoreModerator(moderator);
                }

                // Prüfe ob Kanal schon in lokalen Datensätzen vorhanden ist.
                if (!channelDatabaseManager.IsChannelContained(newManagedChannel.Id))
                {
                    Debug.WriteLine("AddChannelToLocalManagedChannels: Adding channel with id {0} to local channels.",
                        newManagedChannel.Id);
                    // Wenn nicht, füge Kanal hinzu. 
                    AddToLocalChannels(newManagedChannel);
                }
                else
                {
                    // Frage lokale Version ab und prüfe, ob diese aktualisiert werden muss.
                    Channel localChannel = GetChannel(newManagedChannel.Id);

                    if (DateTimeOffset.Compare(localChannel.ModificationDate, newManagedChannel.ModificationDate) < 0)
                    {
                        Debug.WriteLine("SynchronizeLocalManagedChannels: Need to update channel with id {0}.",
                            localChannel.Id);
                        // Übernehme NotificationSettings von lokalem Kanal.
                        newManagedChannel.AnnouncementNotificationSetting = localChannel.AnnouncementNotificationSetting;
                        // Ersetze lokalen Datensatz durch neuen Datensatz.
                        ReplaceLocalChannel(newManagedChannel);
                    }
                }

                // Füge den Moderator als Verantwortlichen für den Kanal hinzu.
                channelDatabaseManager.AddModeratorToChannel(newManagedChannel.Id, moderator.Id, true);

                // Stoße das Herunterladen der für den neu hinzugekommenen Kanal relevanten Daten an.
                // Bemerkung: Falls das fehlschlägt wird kein Fehler geworfen. Die Daten können auch im Fehlerfall später nachgeladen werden.
                Task.Run(() => retrieveAndStoreManagedChannelInfoAsync(moderator, newManagedChannel.Id));
            }
            catch (DatabaseException ex)
            {
                Debug.WriteLine("Couldn't add channel to local managed channels. Msg is {0}.",
                    ex.Message);
                throw new ClientException(ErrorCodes.LocalDatabaseException, ex.Message);
            }
        }
        /// <summary>
        /// Bereitet ein Objekt vom Typ Channel vor, welches alle Properties enthält, die sich geändert haben.
        /// Die Methode bekommt eine alte Version eines Channel Objekts und eine neue Version und ermittelt 
        /// dann die Properties, die eine Aktualisierung erhalten haben und schreibt diese in eine neue Channel
        /// Instanz. Die von der Methode zurückgelieferte Channel Instanz kann dann direkt für die Aktualisierung auf
        /// dem Server verwendet werden. Achtung: Hat sich überhaupt keine Property geändert, so gibt die Methode null zurück.
        /// </summary>
        /// <param name="oldChannel">Das Channel Objekt vor der Aktualisierung.</param>
        /// <param name="newChannel">Das Channel Objekt mit den aktuellen Werten.</param>
        /// <returns>Ein Objekt der Klasse Channel, bei dem die Properties, die sich geändert haben, mit den
        ///     aktualisierten Werten gefüllt sind.</returns>
        private Channel prepareUpdatableChannelInstance(Channel oldChannel, Channel newChannel)
        {
            bool hasChanged = false;
            Channel updatedChannel = new Channel();

            // Vergleiche zunächst Properties der allgemeinen Channel Klasse.
            if (oldChannel.Name != newChannel.Name)
            {
                hasChanged = true;
                updatedChannel.Name = newChannel.Name;
            }

            if (oldChannel.Description != newChannel.Description)
            {
                hasChanged = true;
                updatedChannel.Description = newChannel.Description;
            }

            if (oldChannel.Term != newChannel.Term)
            {
                hasChanged = true;
                updatedChannel.Term = newChannel.Term;
            }

            if (oldChannel.Locations != newChannel.Locations)
            {
                hasChanged = true;
                updatedChannel.Locations = newChannel.Locations;
            }

            if (oldChannel.Dates != newChannel.Dates)
            {
                hasChanged = true;
                updatedChannel.Dates = newChannel.Dates;
            }

            if (oldChannel.Contacts != newChannel.Contacts)
            {
                hasChanged = true;
                updatedChannel.Contacts = newChannel.Contacts;
            }

            if (oldChannel.Website != newChannel.Website)
            {
                hasChanged = true;
                updatedChannel.Website = newChannel.Website;
            }

            // Vergleiche, ob kanalspezifische Felder sich geändert haben bei den Kanälen eines Typs mit solchen Feldern.
            if (oldChannel.Type == newChannel.Type)
            {
                switch (oldChannel.Type)
                {
                    case ChannelType.LECTURE:
                        Lecture updatedLecture = new Lecture()
                        {
                            Name = updatedChannel.Name,
                            Description = updatedChannel.Description,
                            Type = ChannelType.LECTURE,
                            Term = updatedChannel.Term,
                            Locations = updatedChannel.Locations,
                            Dates = updatedChannel.Dates,
                            Contacts = updatedChannel.Contacts,
                            Website = updatedChannel.Website
                        };

                        Lecture oldLecture = oldChannel as Lecture;
                        Lecture newLecture = newChannel as Lecture;

                        if (oldLecture.Lecturer != newLecture.Lecturer)
                        {
                            hasChanged = true;
                            updatedLecture.Lecturer = newLecture.Lecturer;
                        }

                        if (oldLecture.Assistant != newLecture.Assistant)
                        {
                            hasChanged = true;
                            updatedLecture.Assistant = newLecture.Assistant;
                        }

                        if (oldLecture.Faculty != newLecture.Faculty)
                        {
                            hasChanged = true;
                            updatedLecture.Faculty = newLecture.Faculty;
                        }

                        if (oldLecture.StartDate != newLecture.StartDate)
                        {
                            hasChanged = true;
                            updatedLecture.StartDate = newLecture.StartDate;
                        }

                        if (oldLecture.EndDate != newLecture.EndDate)
                        {
                            hasChanged = true;
                            updatedLecture.EndDate = newLecture.EndDate;
                        }

                        // Setze updatedChannel neu.
                        updatedChannel = updatedLecture;
                        break;
                    case ChannelType.EVENT:
                        Event updatedEvent = new Event()
                        {
                            Name = updatedChannel.Name,
                            Description = updatedChannel.Description,
                            Type = ChannelType.EVENT,
                            Term = updatedChannel.Term,
                            Locations = updatedChannel.Locations,
                            Dates = updatedChannel.Dates,
                            Contacts = updatedChannel.Contacts,
                            Website = updatedChannel.Website
                        };

                        Event oldEvent = oldChannel as Event;
                        Event newEvent = newChannel as Event;

                        if (oldEvent.Cost != newEvent.Cost)
                        {
                            hasChanged = true;
                            updatedEvent.Cost = newEvent.Cost;
                        }

                        if (oldEvent.Organizer != newEvent.Organizer)
                        {
                            hasChanged = true;
                            updatedEvent.Organizer = newEvent.Organizer;
                        }

                        // Setze updatedChannel neu.
                        updatedChannel = updatedEvent;
                        break;
                    case ChannelType.SPORTS:
                        Sports updatedSport = new Sports()
                        {
                            Name = updatedChannel.Name,
                            Description = updatedChannel.Description,
                            Type = ChannelType.SPORTS,
                            Term = updatedChannel.Term,
                            Locations = updatedChannel.Locations,
                            Dates = updatedChannel.Dates,
                            Contacts = updatedChannel.Contacts,
                            Website = updatedChannel.Website
                        };

                        Sports oldSport = oldChannel as Sports;
                        Sports newSport = newChannel as Sports;

                        if (oldSport.Cost != newSport.Cost)
                        {
                            hasChanged = true;
                            updatedSport.Cost = newSport.Cost;
                        }

                        if (oldSport.NumberOfParticipants != newSport.NumberOfParticipants)
                        {
                            hasChanged = true;
                            updatedSport.NumberOfParticipants = newSport.NumberOfParticipants;
                        }

                        // Setze updatedChannel neu.
                        updatedChannel = updatedSport;
                        break;
                    case ChannelType.OTHER:
                        updatedChannel.Type = ChannelType.OTHER;
                        break;
                    case ChannelType.STUDENT_GROUP:
                        updatedChannel.Type = ChannelType.STUDENT_GROUP;
                        break;
                }
            }

            // Prüfe, ob sich überhaupt eine Property geändert hat.
            if (!hasChanged)
            {
                Debug.WriteLine("No Property of channel has been updated. Method will return null.");
                updatedChannel = null;
            }

            return updatedChannel;
        }
        /// <summary>
        /// Hilfsmethode, welche aus den eingegebenen Daten ein Objekt
        /// vom Typ Channel erstellt. Eventuelle Subklassen-Attribute
        /// werden ebenfalls gesetzt.
        /// </summary>
        /// <returns>Ein Objekt der Klasse Channel, welches die vom Nutzer eingegebenen Daten enthält.</returns>
        private Channel createChannelObjectFromEnteredData()
        {
            // Setze den String für das Semester zusammen.
            string termString = string.Empty;
            if (TermYear != null)
            {
                if (IsSummerTermSelected)
                {
                    termString += "S" + TermYear;
                }
                else if (IsWinterTermSelected)
                {
                    termString += "W" + TermYear;
                }
            }

            // Erzeuge Instanz aus den eingegebenen Daten.
            Channel newChannel = null;
            switch (SelectedChannelType)
            {
                case ChannelType.LECTURE:
                    Lecture lecture = new Lecture()
                    {
                        Name = ChannelName,
                        Description = ChannelDescription,
                        Type = SelectedChannelType,
                        Term = termString,
                        Locations = this.Locations,
                        Dates = this.Dates,
                        Contacts = this.Contacts,
                        Website = this.Website,
                        Faculty = SelectedFaculty,
                        StartDate = LectureStartDate,
                        EndDate = LectureEndDate,
                        Lecturer = this.Lecturer,
                        Assistant = this.Assistant
                    };
                    newChannel = lecture;
                    break;
                case ChannelType.EVENT:
                    Event eventObj = new Event()
                    {
                        Name = ChannelName,
                        Description = ChannelDescription,
                        Type = SelectedChannelType,
                        Term = termString,
                        Locations = this.Locations,
                        Dates = this.Dates,
                        Contacts = this.Contacts,
                        Website = this.Website,
                        Cost = EventCost,
                        Organizer = EventOrganizer
                    };
                    newChannel = eventObj;
                    break;
                case ChannelType.SPORTS:
                    Sports sportsObj = new Sports()
                    {
                        Name = ChannelName,
                        Description = ChannelDescription,
                        Type = SelectedChannelType,
                        Term = termString,
                        Locations = this.Locations,
                        Dates = this.Dates,
                        Contacts = this.Contacts,
                        Website = this.Website,
                        Cost = SportsCost,
                        NumberOfParticipants = AmountOfParticipants
                    };
                    newChannel = sportsObj;
                    break;
                default:
                    newChannel = new Channel()
                    {
                        Name = ChannelName,
                        Description = ChannelDescription,
                        Type = SelectedChannelType,
                        Term = termString,
                        Locations = this.Locations,
                        Dates = this.Dates,
                        Contacts = this.Contacts,
                        Website = this.Website
                    };
                    break;
            }

            return newChannel;
        }
        /// <summary>
        /// Führt Aktualisierung des Kanals aus. Es wird ermittelt welche Properties eine Aktualisierung 
        /// erhalten haben. Die Aktualisierungen werden an den Server übermittelt, der die Aktualisierung auf
        /// dem Serverdatensatz ausführt und die Abonnenten über die Änderung informiert.
        /// </summary>
        /// <param name="oldChannel">Der Datensatz des Kanals vor der Aktualisierung.</param>
        /// <param name="newChannel">Der Datensatz mit neu eingegebenen Daten.</param>
        /// <returns>Liefert true, wenn die Aktualisierung erfolgreich war, ansonsten false.</returns>
        /// <exception cref="ClientException">Wirft ClientException, wenn Fehler während des Aktualisierungsvorgangs auftritt.</exception>
        public async Task<bool> UpdateChannelAsync(Channel oldChannel, Channel newChannel)
        {
            if (oldChannel == null || newChannel == null)
                return false;

            Moderator activeModerator = GetLocalModerator();
            if (activeModerator == null)
                return false;

            // Validiere zunächst die neu eingegebenen Daten, bei Validierungsfehlern kann hier gleich abgebrochen werden.
            clearValidationErrors();
            bool validationSuccessful = validateChannelProperties(newChannel);

            if (!validationSuccessful)
                return false;

            // Erstelle ein Objekt für die Aktualisierung, welches die Daten enthält, die aktualisiert werden müssen.
            Channel updatableChannelObj = prepareUpdatableChannelInstance(oldChannel, newChannel);

            if (updatableChannelObj == null)
                return true;    // Keine Aktualisierung nötig.

            // Erstelle JSON-Dokument für die Aktualisierung.
            string jsonContent = jsonParser.ParseChannelToJsonString(updatableChannelObj);
            if (jsonContent == null)
            {
                Debug.WriteLine("Channel object could not be translated to a json document.");
                return false;
            }

            // Server Request.
            string serverResponse = null;
            try
            {
                // Führe Request zur Aktualisierung des Inhalts aus.
                serverResponse = await channelApi.SendUpdateChannelRequestAsync(
                    activeModerator.ServerAccessToken,
                    oldChannel.Id,
                    jsonContent);
            }
            catch (APIException ex)
            {
                if (ex.ErrorCode == ErrorCodes.ChannelNotFound)
                {
                    Debug.WriteLine("Channel not found on server. Channel probably deleted.");
                    // Behandlung Not Found. Kanal wahrscheinlich gelöscht.
                    MarkChannelAsDeleted(oldChannel.Id);
                }

                // Bilde ab auf ClientException.
                throw new ClientException(ex.ErrorCode, ex.Message);
            }

            // Führe lokale Aktualisierung des Datensatzes aus.
            try
            {
                Channel updatedChannel = jsonParser.ParseChannelFromJson(serverResponse);
                if (updatedChannel == null)
                {
                    throw new ClientException(ErrorCodes.JsonParserError, "Couldn't parse server response.");
                }

                // Notification Settings bleiben unverändert.
                updatedChannel.AnnouncementNotificationSetting = oldChannel.AnnouncementNotificationSetting;
                if (updatedChannel != null)
                {
                    channelDatabaseManager.UpdateChannelWithSubclass(updatedChannel);
                }
            }
            catch (DatabaseException ex)
            {
                Debug.WriteLine("DatabaseException. Couldn't perform local channel update.");
                throw new ClientException(ErrorCodes.LocalDatabaseException, ex.Message);
            }

            return true;
        }
 /// <summary>
 /// Aktualisiert nur die Properties, welche für die View aktuell relevant sind, also Properties, die
 /// per Databinding an die View gebunden sind. Aktualisiert dabei die 
 /// </summary>
 /// <param name="updatableChannel">Das zu aktualisierende Channel Objekt.</param>
 /// <param name="newChannel">Das Channel Objekt mit den neuen Daten.</param>
 protected void updateViewRelatedPropertiesOfChannel(Channel updatableChannel, Channel newChannel)
 {
     updatableChannel.Name = newChannel.Name;
     updatableChannel.Term = newChannel.Term;
 }
        /// <summary>
        /// Erstellt ein JSON Dokument aus einem Channel Objekt.
        /// </summary>
        /// <param name="channel">Das Objekt, das umgewandelt werden soll.</param>
        /// <returns>JSON-Dokument des Objekts, oder null, falls Serialisierung fehlgeschlagen ist.</returns>
        public string ParseChannelToJsonString(Channel channel)
        {
            if (channel == null)
                return null;

            string jsonContent = null;
            try
            {
                switch (channel.Type)
                {
                    case ChannelType.LECTURE:
                        Lecture lecture = channel as Lecture;
                        jsonContent = JsonConvert.SerializeObject(lecture);
                        break;
                    case ChannelType.EVENT:
                        Event eventObj = channel as Event;
                        jsonContent = JsonConvert.SerializeObject(eventObj);
                        break;
                    case ChannelType.SPORTS:
                        Sports sportObj = channel as Sports;
                        jsonContent = JsonConvert.SerializeObject(sportObj);
                        break;
                    default:
                        jsonContent = JsonConvert.SerializeObject(channel);
                        break;
                }
            }
            catch (JsonException jsonEx)
            {
                Debug.WriteLine("JsonParsingManager: Exception during serialization of an channel object.");
                Debug.WriteLine("JsonParsingManager: Message is: {0}.", jsonEx.Message);
            }

            return jsonContent;
        }