/*
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Florin Patan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.goide.dlv;
import com.goide.dlv.protocol.DlvRequest;
import com.goide.dlv.protocol.DlvResponse;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.concurrency.Promise;
import org.jetbrains.rpc.CommandProcessor;
import org.jetbrains.rpc.CommandProcessorKt;
import org.jetbrains.rpc.RequestCallback;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public abstract class DlvCommandProcessor extends CommandProcessor<JsonReaderEx, DlvResponse, DlvResponse> {
@Nullable
@Override
public DlvResponse readIfHasSequence(@NotNull JsonReaderEx message) {
return new DlvResponse.CommandResponseImpl(message, null);
}
@Override
public int getSequence(@NotNull DlvResponse response) {
return response.id();
}
@Override
public void acceptNonSequence(JsonReaderEx message) {
}
public void processIncomingJson(@NotNull JsonReaderEx reader) {
getMessageManager().processIncoming(reader);
}
@Override
public void call(@NotNull DlvResponse response, @NotNull RequestCallback<DlvResponse> callback) {
if (response.result() != null) {
callback.onSuccess(response, this);
}
else {
callback.onError(Promise.createError(createMessage(response)));
}
}
@NotNull
private static String createMessage(@NotNull DlvResponse r) {
DlvResponse.ErrorInfo e = r.error();
if (e == null) return "Internal messaging error";
List<String> data = e.data();
String message = e.message();
if (ContainerUtil.isEmpty(data)) return StringUtil.defaultIfEmpty(message, "<null>");
List<String> list = ContainerUtil.newSmartList(message);
list.addAll(data);
return list.toString();
}
@NotNull
@Override
public <RESULT> RESULT readResult(@NotNull String method, @NotNull DlvResponse successResponse) {
JsonReaderEx result = successResponse.result();
assert result != null : "success result should be not null";
JsonReader reader = result.asGson();
Object o = new GsonBuilder().create().fromJson(reader, getResultType(method.replaceFirst("RPCServer\\.", "")));
//noinspection unchecked
return (RESULT)o;
}
@NotNull
private static Type getResultType(@NotNull String method) {
for (Class<?> c : DlvRequest.class.getDeclaredClasses()) {
if (method.equals(c.getSimpleName())) {
Type s = c.getGenericSuperclass();
assert s instanceof ParameterizedType : c.getCanonicalName() + " should have a generic parameter for correct callback processing";
Type[] arguments = ((ParameterizedType)s).getActualTypeArguments();
assert arguments.length == 1 : c.getCanonicalName() + " should have only one generic argument for correct callback processing";
return arguments[0];
}
}
CommandProcessorKt.getLOG().error("Unknown response " + method + ", please register an appropriate request into com.goide.dlv.protocol.DlvRequest");
return Object.class;
}
}