/*
* Copyright 2013 Martin Kouba
*
* 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 org.trimou.gson.resolver;
import static org.trimou.engine.priority.Priorities.rightBefore;
import java.util.Collections;
import java.util.Set;
import org.trimou.engine.config.ConfigurationKey;
import org.trimou.engine.config.SimpleConfigurationKey;
import org.trimou.engine.resolver.IndexResolver;
import org.trimou.engine.resolver.MapResolver;
import org.trimou.engine.resolver.Placeholder;
import org.trimou.engine.resolver.ResolutionContext;
import org.trimou.gson.converter.GsonValueConverter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
/**
* Gson's parser API resolver.
*
* @author Martin Kouba
* @see <a href="http://code.google.com/p/google-gson/">http://code.google.com/p
* /google-gson/</a>
*/
public class JsonElementResolver extends IndexResolver {
public static final int JSON_ELEMENT_RESOLVER_PRIORITY = rightBefore(
MapResolver.MAP_RESOLVER_PRIORITY);
/**
* Use this name if you want to unwrap the current context object (note that
* "this" would be normally matched by ThisResolver)
*/
public static final String NAME_UNWRAP_THIS = "unwrapThis";
/**
* If set to <code>true</code> instances of {@link JsonPrimitive} and
* {@link JsonNull} instances are unwrapped automatically.
* <p>
* Since 2.1 automatic unwrapping is disabled by default. See also
* {@link GsonValueConverter}.
*/
public static final ConfigurationKey UNWRAP_JSON_PRIMITIVE_KEY = new SimpleConfigurationKey(
JsonElementResolver.class.getName() + ".unwrapJsonPrimitive",
false);
private boolean unwrapJsonPrimitive;
private final Hint hint;
/**
*
*/
public JsonElementResolver() {
this(JSON_ELEMENT_RESOLVER_PRIORITY);
}
/**
* @param priority
*/
public JsonElementResolver(int priority) {
super(priority);
this.hint = JsonElementResolver.this::resolve;
}
@Override
public Object resolve(Object contextObject, String name,
ResolutionContext context) {
if (contextObject == null || !(contextObject instanceof JsonElement)) {
return null;
}
JsonElement element = (JsonElement) contextObject;
if (element.isJsonArray() && isAnIndex(name)) {
// Index-based access of JsonArray elements
JsonArray jsonArray = (JsonArray) element;
// #26 Unwrap the element if necessary
final Integer index = getIndexValue(name, context.getKey(),
jsonArray.size());
if (index != null) {
return unwrapJsonElementIfNecessary(jsonArray.get(index),
unwrapJsonPrimitive);
}
} else if (element.isJsonObject()) {
// JsonObject properties
JsonObject jsonObject = (JsonObject) element;
JsonElement member = jsonObject.get(name);
if (member != null) {
return unwrapJsonElementIfNecessary(member,
unwrapJsonPrimitive);
}
} else if (name.equals(NAME_UNWRAP_THIS)) {
return unwrapJsonElementIfNecessary(element, true);
}
return null;
}
@Override
public void init() {
unwrapJsonPrimitive = configuration
.getBooleanPropertyValue(UNWRAP_JSON_PRIMITIVE_KEY);
}
@Override
public Set<ConfigurationKey> getConfigurationKeys() {
return Collections.singleton(UNWRAP_JSON_PRIMITIVE_KEY);
}
@Override
public Hint createHint(Object contextObject, String name,
ResolutionContext context) {
return hint;
}
private Object unwrapJsonElementIfNecessary(JsonElement jsonElement,
boolean unwrapJsonPrimitive) {
if (unwrapJsonPrimitive) {
if (jsonElement.isJsonPrimitive()) {
return unwrapJsonPrimitive((JsonPrimitive) jsonElement);
} else if (jsonElement.isJsonNull()) {
return Placeholder.NULL;
}
}
return jsonElement;
}
private Object unwrapJsonPrimitive(JsonPrimitive jsonPrimitive) {
if (jsonPrimitive.isBoolean()) {
return jsonPrimitive.getAsBoolean();
} else if (jsonPrimitive.isString()) {
return jsonPrimitive.getAsString();
} else if (jsonPrimitive.isNumber()) {
return jsonPrimitive.getAsNumber();
}
return jsonPrimitive;
}
}