From 06d7bc8d84c40dffa1f7bf5c3082e58960e18398 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Mon, 12 Sep 2016 22:51:43 +0200
Subject: [PATCH] Fixed invocation issues

---
 .../backlogstorage/BacklogStorage.java        |   2 +
 .../backlogstorage/HybridBacklogStorage.java  |   5 +
 .../syncables/types/impl/BufferSyncer.java    |   1 +
 .../syncables/types/interfaces/QNetwork.java  |   2 +-
 .../types/invokers/IAliasManager.java         |  12 +-
 .../types/invokers/IBacklogManager.java       |  15 ++-
 .../types/invokers/IBufferSyncer.java         |  27 +++--
 .../types/invokers/IBufferViewConfig.java     |  48 +++++---
 .../types/invokers/IBufferViewManager.java    |  15 ++-
 .../types/invokers/ICertManager.java          |  12 +-
 .../syncables/types/invokers/IClient.java     |  49 +++++---
 .../syncables/types/invokers/ICoreInfo.java   |  12 +-
 .../syncables/types/invokers/IIdentity.java   |  72 ++++++++----
 .../types/invokers/IIgnoreListManager.java    |  18 ++-
 .../syncables/types/invokers/IIrcChannel.java |  42 +++++--
 .../syncables/types/invokers/IIrcUser.java    |  75 ++++++++----
 .../syncables/types/invokers/INetwork.java    | 111 ++++++++++++------
 .../types/invokers/INetworkConfig.java        |  33 ++++--
 .../syncables/types/invokers/Invoker.java     |   3 +-
 .../types/invokers/InvokerRegistry.java       |   3 +-
 20 files changed, 385 insertions(+), 172 deletions(-)

diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java
index d215a841f..ba833ae85 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java
@@ -61,4 +61,6 @@ public interface BacklogStorage {
     Set<BacklogFilter> getFilters();
 
     void setMarkerLine(@IntRange(from = 0) int buffer, int msgId);
+
+    void merge(@IntRange(from = 0) int buffer1, @IntRange(from = 0) int buffer2);
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java
index d9514a2be..c527571e4 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java
@@ -214,6 +214,11 @@ public class HybridBacklogStorage implements BacklogStorage {
         }
     }
 
+    @Override
+    public void merge(@IntRange(from = 0) int buffer1, @IntRange(from = 0) int buffer2) {
+        SQLite.update(Message.class).set(Message_Table.bufferInfo_id.eq(buffer1)).where(Message_Table.bufferInfo_id.eq(buffer2)).execute();
+    }
+
     private void ensureExisting(@IntRange(from = -1) int bufferId) {
         assertNotNull(client);
         if (backlogs.get(bufferId) == null) {
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java
index 6ad4f4980..e8a372134 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java
@@ -160,6 +160,7 @@ public class BufferSyncer extends ABufferSyncer {
 
     @Override
     public void _mergeBuffersPermanently(int buffer1, int buffer2) {
+        client.backlogStorage().merge(buffer1, buffer2);
         _removeBuffer(buffer2);
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
index 5174f07ce..517ce6be7 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
@@ -235,6 +235,7 @@ public interface QNetwork extends QObservable<QNetwork> {
     void setUseSasl(boolean useSasl);
 
     void setSaslPassword(final String saslPassword);
+
     void _setUseSasl(boolean useSasl);
 
     @Synced
@@ -243,7 +244,6 @@ public interface QNetwork extends QObservable<QNetwork> {
     void _setSaslAccount(final String saslAccount);
 
     @Synced
-
     void _setSaslPassword(final String saslPassword);
 
     @Synced
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java
index 43f225d31..979a72de5 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QAliasManager;
 
@@ -39,14 +40,19 @@ public class IAliasManager implements Invoker<QAliasManager> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QAliasManager obj) {
+    public void invoke(SyncFunction function, QAliasManager obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "addAlias": {
                 obj._addAlias((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java
index b06d6ea86..1d5d8619f 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import java.util.List;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
@@ -42,17 +43,23 @@ public class IBacklogManager implements Invoker<QBacklogManager> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QBacklogManager obj) {
+    public void invoke(SyncFunction function, QBacklogManager obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "receiveBacklog": {
                 obj._receiveBacklog((int) function.params.get(0), (int) function.params.get(1), (int) function.params.get(2), (int) function.params.get(3), (int) function.params.get(4), (List<Message>) function.params.get(5));
-            } break;
+            }
+            break;
             case "receiveBacklogAll": {
                 obj._receiveBacklogAll((int) function.params.get(0), (int) function.params.get(1), (int) function.params.get(2), (int) function.params.get(3), (List<Message>) function.params.get(4));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java
index 716eca811..0f5fe0d24 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferSyncer;
 
@@ -39,29 +40,39 @@ public class IBufferSyncer implements Invoker<QBufferSyncer> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QBufferSyncer obj) {
+    public void invoke(SyncFunction function, QBufferSyncer obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setLastSeenMsg": {
                 obj._setLastSeenMsg((int) function.params.get(0), (int) function.params.get(1));
-            } break;
+            }
+            break;
             case "setMarkerLine": {
                 obj._setMarkerLine((int) function.params.get(0), (int) function.params.get(1));
-            } break;
+            }
+            break;
             case "removeBuffer": {
                 obj._removeBuffer((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "renameBuffer": {
                 obj._renameBuffer((int) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "mergeBuffersPermanently": {
                 obj._mergeBuffersPermanently((int) function.params.get(0), (int) function.params.get(1));
-            } break;
+            }
+            break;
             case "markBufferAsRead": {
                 obj._markBufferAsRead((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java
index d775f3773..49c326689 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 
@@ -39,50 +40,67 @@ public class IBufferViewConfig implements Invoker<QBufferViewConfig> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QBufferViewConfig obj) {
+    public void invoke(SyncFunction function, QBufferViewConfig obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setBufferViewName": {
                 obj._setBufferViewName((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setNetworkId": {
                 obj._setNetworkId((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAddNewBuffersAutomatically": {
                 obj._setAddNewBuffersAutomatically((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setSortAlphabetically": {
                 obj._setSortAlphabetically((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setDisableDecoration": {
                 obj._setDisableDecoration((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAllowedBufferTypes": {
                 obj._setAllowedBufferTypes((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setMinimumActivity": {
                 obj._setMinimumActivity((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setHideInactiveBuffers": {
                 obj._setHideInactiveBuffers((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setHideInactiveNetworks": {
                 obj._setHideInactiveNetworks((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "addBuffer": {
                 obj._addBuffer((int) function.params.get(0), (int) function.params.get(1));
-            } break;
+            }
+            break;
             case "moveBuffer": {
                 obj._moveBuffer((int) function.params.get(0), (int) function.params.get(1));
-            } break;
+            }
+            break;
             case "removeBuffer": {
                 obj._removeBuffer((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "removeBufferPermanently": {
                 obj._removeBufferPermanently((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java
index 042f705f5..cfe99ffc2 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 
@@ -39,17 +40,23 @@ public class IBufferViewManager implements Invoker<QBufferViewManager> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QBufferViewManager obj) {
+    public void invoke(SyncFunction function, QBufferViewManager obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "addBufferViewConfig": {
                 obj._addBufferViewConfig((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "deleteBufferViewConfig": {
                 obj._deleteBufferViewConfig((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java
index 959cc69e4..f39f20b9b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QCertManager;
 
@@ -39,14 +40,19 @@ public class ICertManager implements Invoker<QCertManager> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QCertManager obj) {
+    public void invoke(SyncFunction function, QCertManager obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "": {
 
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IClient.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IClient.java
index 7e7777385..76a143bb0 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IClient.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IClient.java
@@ -24,6 +24,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 import android.support.annotation.NonNull;
 
 import de.kuschku.libquassel.client.QClient;
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.RpcCallFunction;
 import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
@@ -41,35 +42,47 @@ public class IClient {
         return invoker;
     }
 
-    public void invoke(RpcCallFunction function, QClient obj) {
+    public void invoke(RpcCallFunction function, QClient obj) throws SyncInvocationException {
         switch (function.functionName) {
-            case "2displayMsg": {
+            case "2displayMsg(Message)": {
                 obj._displayMsg((Message) function.params.get(0));
-            } break;
-            case "2bufferInfoUpdated": {
+            }
+            break;
+            case "2bufferInfoUpdated(BufferInfo)": {
                 obj._bufferInfoUpdated((BufferInfo) function.params.get(0));
-            } break;
-            case "2identityCreated": {
+            }
+            break;
+            case "2identityCreated(Identity)": {
                 obj._identityCreated((Identity) function.params.get(0));
-            } break;
-            case "2identityRemoved": {
+            }
+            break;
+            case "2identityRemoved(IdentityId)": {
                 obj._identityRemoved((int) function.params.get(0));
-            } break;
-            case "2networkCreated": {
+            }
+            break;
+            case "2networkCreated(NetworkId)": {
                 obj._networkCreated((int) function.params.get(0));
-            } break;
-            case "2networkRemoved": {
+            }
+            break;
+            case "2networkRemoved(NetworkId)": {
                 obj._networkRemoved((int) function.params.get(0));
-            } break;
-            case "2passwordChanged": {
+            }
+            break;
+            case "2passwordChanged(PeerPtr,bool)": {
                 obj._passwordChanged((long) function.params.get(0), (boolean) function.params.get(1));
-            } break;
-            case "2displayStatusMsg": {
+            }
+            break;
+            case "2displayStatusMsg(QString,QString)": {
                 obj._displayStatusMsg((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "__objectRenamed__": {
                 obj.___objectRenamed__((String) function.params.get(0), (String) function.params.get(1), (String) function.params.get(2));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException("Client::" + function.functionName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java
index 03fd4c591..01617bb07 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import java.util.Map;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.interfaces.QCoreInfo;
@@ -42,14 +43,19 @@ public class ICoreInfo implements Invoker<QCoreInfo> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QCoreInfo obj) {
+    public void invoke(SyncFunction function, QCoreInfo obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setCoreData": {
                 obj._setCoreData((Map<String, QVariant>) function.params.get(0));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java
index 71cb0e8ff..429f8cc5b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import java.util.List;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QIdentity;
 
@@ -41,74 +42,99 @@ public class IIdentity implements Invoker<QIdentity> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QIdentity obj) {
+    public void invoke(SyncFunction function, QIdentity obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setId": {
                 obj._setId((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setIdentityName": {
                 obj._setIdentityName((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setRealName": {
                 obj._setRealName((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setNicks": {
                 obj._setNicks((List<String>) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAwayNick": {
                 obj._setAwayNick((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAwayNickEnabled": {
                 obj._setAwayNickEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAwayReason": {
                 obj._setAwayReason((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAwayReasonEnabled": {
                 obj._setAwayReasonEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoAwayEnabled": {
                 obj._setAutoAwayEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoAwayTime": {
                 obj._setAutoAwayTime((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoAwayReason": {
                 obj._setAutoAwayReason((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoAwayReasonEnabled": {
                 obj._setAutoAwayReasonEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setDetachAwayEnabled": {
                 obj._setDetachAwayEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setDetachAwayReason": {
                 obj._setDetachAwayReason((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setDetachAwayReasonEnabled": {
                 obj._setDetachAwayReasonEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setIdent": {
                 obj._setIdent((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setKickReason": {
                 obj._setKickReason((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setPartReason": {
                 obj._setPartReason((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setQuitReason": {
                 obj._setQuitReason((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setSslKey": {
                 obj._setSslKey((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setSslCert": {
                 obj._setSslCert((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java
index 92bd78a89..41347cc71 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
 
@@ -38,20 +39,27 @@ public class IIgnoreListManager implements Invoker<QIgnoreListManager> {
         return invoker;
     }
 
-    public void invoke(SyncFunction function, QIgnoreListManager object) {
+    public void invoke(SyncFunction function, QIgnoreListManager object) throws SyncInvocationException {
         switch (function.methodName) {
             case "removeIgnoreListItem": {
                 object._removeIgnoreListItem((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "toggleIgnoreRule": {
                 object._toggleIgnoreRule((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "addIgnoreListItem": {
                 object._addIgnoreListItem((int) function.params.get(0), (String) function.params.get(1), (boolean) function.params.get(2), (int) function.params.get(3), (int) function.params.get(4), (String) function.params.get(5), (boolean) function.params.get(6));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(object, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java
index d2dd9ccf6..6120c7df9 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import java.util.List;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
 
@@ -41,44 +42,59 @@ public class IIrcChannel implements Invoker<QIrcChannel> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QIrcChannel obj) {
+    public void invoke(SyncFunction function, QIrcChannel obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setTopic": {
                 obj._setTopic((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setPassword": {
                 obj._setPassword((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setEncrypted": {
                 obj._setEncrypted((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "joinIrcUsers": {
                 obj._joinIrcUsers((List<String>) function.params.get(0), (List<String>) function.params.get(1));
-            } break;
+            }
+            break;
             case "part": {
                 obj._part((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUserModes": {
                 obj._setUserModes((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "addUserMode": {
                 obj._addUserMode((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "removeUserMode": {
                 obj._removeUserMode((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "addChannelMode": {
                 obj._addChannelMode((char) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "removeChannelMode": {
                 obj._removeChannelMode((char) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "ircUserNickChanged": {
                 obj._ircUserNickChanged((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java
index eb3b3d66e..46b0019c5 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import org.joda.time.DateTime;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 
@@ -41,77 +42,103 @@ public class IIrcUser implements Invoker<QIrcUser> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QIrcUser obj) {
+    public void invoke(SyncFunction function, QIrcUser obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setAway": {
                 obj._setAway((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUser": {
                 obj._setUser((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setHost": {
                 obj._setHost((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setNick": {
                 obj._setNick((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setRealName": {
                 obj._setRealName((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAccount": {
                 obj._setAccount((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAwayMessage": {
                 obj._setAwayMessage((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setIdleTime": {
                 obj._setIdleTime((DateTime) function.params.get(0));
-            } break;
+            }
+            break;
             case "setLoginTime": {
                 obj._setLoginTime((DateTime) function.params.get(0));
-            } break;
+            }
+            break;
             case "setServer": {
                 obj._setServer((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setIrcOperator": {
                 obj._setIrcOperator((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setLastAwayMessage": {
                 obj._setLastAwayMessage((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setWhoisServiceReply": {
                 obj._setWhoisServiceReply((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setSuserHost": {
                 obj._setSuserHost((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setEncrypted": {
                 obj._setEncrypted((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "updateHostmask": {
                 obj._updateHostmask((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUserModes": {
                 obj._setUserModes((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "joinChannel": {
                 obj._joinChannel((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "partChannel": {
                 obj._partChannel((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "addUserModes": {
                 obj._addUserModes((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "removeUserModes": {
                 obj._removeUserModes((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "quit": {
                 obj._quit();
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java
index 477dd548a..217cd57cc 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import java.util.List;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.objects.types.NetworkServer;
 import de.kuschku.libquassel.syncables.types.impl.NetworkInfo;
@@ -43,116 +44,154 @@ public class INetwork implements Invoker<QNetwork> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QNetwork obj) {
+    public void invoke(SyncFunction function, QNetwork obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setAutoAwayActive": {
                 obj._setAutoAwayActive((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setNetworkName": {
                 obj._setNetworkName((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setCurrentServer": {
                 obj._setCurrentServer((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setConnected": {
                 obj._setConnected((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setConnectionState": {
                 obj._setConnectionState((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setMyNick": {
                 obj._setMyNick((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setLatency": {
                 obj._setLatency((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setIdentity": {
                 obj._setIdentity((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setServerList": {
                 obj._setServerList((List<NetworkServer>) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUseRandomServer": {
                 obj._setUseRandomServer((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setPerform": {
                 obj._setPerform((List<String>) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUseAutoIdentify": {
                 obj._setUseAutoIdentify((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoIdentifyService": {
                 obj._setAutoIdentifyService((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoIdentifyPassword": {
                 obj._setAutoIdentifyPassword((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUseSasl": {
                 obj._setUseSasl((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setSaslAccount": {
                 obj._setSaslAccount((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setSaslPassword": {
                 obj._setSaslPassword((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUseAutoReconnect": {
                 obj._setUseAutoReconnect((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoReconnectInterval": {
                 obj._setAutoReconnectInterval((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoReconnectRetries": {
                 obj._setAutoReconnectRetries((short) function.params.get(0));
-            } break;
+            }
+            break;
             case "setUnlimitedReconnectRetries": {
                 obj._setUnlimitedReconnectRetries((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setRejoinChannels": {
                 obj._setRejoinChannels((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setCodecForServer": {
                 obj._setCodecForServer((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setCodecForEncoding": {
                 obj._setCodecForEncoding((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setCodecForDecoding": {
                 obj._setCodecForDecoding((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "addSupport": {
                 if (function.params.size() == 1)
                     obj._addSupport((String) function.params.get(0));
                 else if (function.params.size() == 2)
                     obj._addSupport((String) function.params.get(0), (String) function.params.get(1));
-            } break;
+            }
+            break;
             case "removeSupport": {
                 obj._removeSupport((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "addIrcUser": {
                 obj._addIrcUser((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "addIrcChannel": {
                 obj._addIrcChannel((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "updateNickFromMask": {
                 obj._updateNickFromMask((String) function.params.get(0));
-            } break;
+            }
+            break;
             case "setNetworkInfo": {
                 obj._setNetworkInfo((NetworkInfo) function.params.get(0));
-            } break;
+            }
+            break;
             case "connect": {
                 obj._connect();
-            } break;
+            }
+            break;
             case "disconnect": {
                 obj._disconnect();
-            } break;
+            }
+            break;
             case "removeChansAndUsers": {
                 obj._removeChansAndUsers();
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java
index c7b9fdbb9..43383232b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java
@@ -23,6 +23,7 @@ package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetworkConfig;
 
@@ -39,35 +40,47 @@ public class INetworkConfig implements Invoker<QNetworkConfig> {
     }
 
     @Override
-    public void invoke(SyncFunction function, QNetworkConfig obj) {
+    public void invoke(SyncFunction function, QNetworkConfig obj) throws SyncInvocationException {
         switch (function.methodName) {
             case "setPingTimeoutEnabled": {
                 obj._setPingTimeoutEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setPingInterval": {
                 obj._setPingInterval((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setMaxPingCount": {
                 obj._setMaxPingCount((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoWhoEnabled": {
                 obj._setAutoWhoEnabled((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoWhoInterval": {
                 obj._setAutoWhoInterval((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoWhoNickLimit": {
                 obj._setAutoWhoNickLimit((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setAutoWhoDelay": {
                 obj._setAutoWhoDelay((int) function.params.get(0));
-            } break;
+            }
+            break;
             case "setStandardCtcp": {
                 obj._setStandardCtcp((boolean) function.params.get(0));
-            } break;
+            }
+            break;
             case "update": {
                 InvokerHelper.update(obj, function.params.get(0));
-            } break;
+            }
+            break;
+            default: {
+                throw new SyncInvocationException(function.className + "::" + function.methodName);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java
index 56f1fb88f..3a9b88f90 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java
@@ -21,8 +21,9 @@
 
 package de.kuschku.libquassel.syncables.types.invokers;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 
 public interface Invoker<T> {
-    void invoke(SyncFunction function, T obj);
+    void invoke(SyncFunction function, T obj) throws SyncInvocationException;
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java
index f13714dce..c8d762613 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java
@@ -21,6 +21,7 @@
 
 package de.kuschku.libquassel.syncables.types.invokers;
 
+import de.kuschku.libquassel.exceptions.SyncInvocationException;
 import de.kuschku.libquassel.functions.types.SyncFunction;
 
 public class InvokerRegistry {
@@ -59,7 +60,7 @@ public class InvokerRegistry {
         }
     }
 
-    public static void invoke(SyncFunction function, Object obj) {
+    public static void invoke(SyncFunction function, Object obj) throws SyncInvocationException {
         Invoker invoker = getInvoker(function);
         if (invoker != null)
             invoker.invoke(function, obj);
-- 
GitLab