/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.jsonrpc;
import elemental.json.JsonArray;
import elemental.json.JsonFactory;
import elemental.json.JsonObject;
import elemental.json.JsonType;
import elemental.json.JsonValue;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcParams;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcRequest;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcResponse;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcResult;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcUnmarshaller;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static elemental.json.JsonType.ARRAY;
import static elemental.json.JsonType.BOOLEAN;
import static elemental.json.JsonType.NUMBER;
import static elemental.json.JsonType.STRING;
import static java.util.Collections.singletonList;
@Singleton
public class ElementalJsonRpcUnmarshaller implements JsonRpcUnmarshaller {
private final JsonFactory jsonFactory;
@Inject
public ElementalJsonRpcUnmarshaller(JsonFactory jsonFactory) {
this.jsonFactory = jsonFactory;
}
@Override
public List<String> unmarshalArray(String message) {
return getArray(message, jsonFactory.parse(message));
}
@Override
public JsonRpcRequest unmarshalRequest(String message) {
checkNotNull(message, "Message must not be null");
checkArgument(!message.isEmpty(), "Message must not be empty");
JsonObject jsonObject = jsonFactory.parse(message);
String id = getId(jsonObject);
String method = getMethod(jsonObject);
JsonRpcParams params = getParams(jsonObject);
return new JsonRpcRequest(id, method, params);
}
@Override
public JsonRpcResponse unmarshalResponse(String message) {
checkNotNull(message, "Message must not be null");
checkArgument(!message.isEmpty(), "Message must not be empty");
JsonObject response = jsonFactory.parse(message);
String id = getId(response);
JsonRpcResult result = getResult(response);
JsonRpcError error = getError(response);
return new JsonRpcResponse(id, result, error);
}
private JsonRpcError getError(JsonObject response) {
if (response.hasKey("error")) {
JsonObject errorJsonValue = response.get("error");
int code = ((Double)errorJsonValue.get("code").asNumber()).intValue();
String errorMessage = errorJsonValue.get("message").asString();
return new JsonRpcError(code, errorMessage);
} else {
return null;
}
}
private JsonRpcResult getResult(JsonObject response) {
if (!response.hasKey("result")) {
return null;
}
JsonValue jsonValue = response.get("result");
if (!jsonValue.getType().equals(ARRAY)) {
return new JsonRpcResult(getInnerItem(jsonValue));
}
JsonArray jsonArray = (JsonArray)jsonValue;
int size = jsonArray.length();
List<Object> innerResults = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
JsonValue innerJsonElement = jsonArray.get(i);
Object innerItem = getInnerItem(innerJsonElement);
innerResults.add(innerItem);
}
return new JsonRpcResult(innerResults);
}
private JsonRpcParams getParams(JsonObject jsonObject) {
if (!jsonObject.hasKey("params")) {
return null;
}
JsonValue jsonValue = jsonObject.get("params");
if (!jsonValue.getType().equals(ARRAY)) {
return new JsonRpcParams(getInnerItem(jsonValue));
}
JsonArray jsonArray = (JsonArray)jsonValue;
int size = jsonArray.length();
List<Object> innerParameters = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
JsonValue innerJsonElement = jsonArray.get(i);
Object innerItem = getInnerItem(innerJsonElement);
innerParameters.add(innerItem);
}
return new JsonRpcParams(innerParameters);
}
private String getId(JsonObject jsonObject) {
return !jsonObject.hasKey("id") ? null : jsonObject.get("id").asString();
}
private String getMethod(JsonObject jsonObject) {
return jsonObject.get("method").asString();
}
private Object getInnerItem(JsonValue jsonElement) {
JsonType type = jsonElement.getType();
if (NUMBER.equals(type)) {
return null;
} else if (NUMBER.equals(type)) {
return jsonElement.asNumber();
} else if (STRING.equals(type)) {
return jsonElement.asString();
} else if (BOOLEAN.equals(type)) {
return jsonElement.asBoolean();
} else {
return jsonElement;
}
}
private List<String> getArray(String message, JsonValue jsonValue) {
if (!ARRAY.equals(jsonValue.getType())) {
return singletonList(message);
}
JsonArray jsonArray = jsonFactory.parse(message);
int size = jsonArray.length();
List<String> result = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
JsonValue jsonElement = jsonArray.get(i);
result.add(jsonElement.toString());
}
return result;
}
}