com.ibm.common.activitystreams.internal.ASObjectAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.common.activitystreams.internal.ASObjectAdapter.java

Source

/**
 * Copyright 2013 OpenSocial Foundation
 * Copyright 2013 International Business Machines Corporation
 *
 * 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.
 *
 * Utility library for working with Activity Streams Actions
 * Requires underscorejs.
 *
 * @author James M Snell (jasnell@us.ibm.com)
 */
package com.ibm.common.activitystreams.internal;

import static com.google.common.collect.ImmutableList.builder;
import static com.ibm.common.activitystreams.Makers.activity;
import static com.ibm.common.activitystreams.Makers.collection;
import static com.ibm.common.activitystreams.Makers.object;

import java.lang.reflect.Type;
import java.util.Map.Entry;

import com.google.common.base.Converter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.ibm.common.activitystreams.ASObject;
import com.ibm.common.activitystreams.Activity;
import com.ibm.common.activitystreams.Collection;
import com.ibm.common.activitystreams.LinkValue;
import com.ibm.common.activitystreams.Makers;
import com.ibm.common.activitystreams.TypeValue;

/**
 * @author james
 * @version $Revision: 1.0 $
 */
public class ASObjectAdapter extends Adapter<ASObject> {

    private final Schema schema;

    protected Schema schema() {
        return schema;
    }

    /**
     * Constructor for ASObjectAdapter.
     * @param schema Schema
     */
    protected ASObjectAdapter(Schema schema) {
        this.schema = schema;
    }

    /**
     * Method serialize.
     * @param obj ASObject
     * @param type Type
     * @param context JsonSerializationContext
        
     * @return JsonElement */
    public final JsonElement serialize(ASObject obj, Type type, JsonSerializationContext context) {
        JsonObject el = new JsonObject();
        for (String key : obj) {
            Object val = obj.get(key);
            if (val != null) {
                el.add(key, context.serialize(val, val.getClass()));
            }
        }
        return el;

    }

    private static final ImmutableSet<? extends Type> knownTypes = ImmutableSet.of(Collection.class,
            Activity.class);

    protected boolean knowsType(Type type) {
        return knownTypes.contains(type);
    }

    protected ASObject.AbstractBuilder<?, ?> builderFor(Type type) {
        if (type == Collection.class)
            return collection();
        else if (type == Activity.class)
            return activity();
        else
            return null;
    }

    protected Model modelFor(Type type) {
        if (type == Collection.class)
            return schema.forObjectClassOrType(Collection.Builder.class, "collection");
        else if (type == Activity.class)
            return schema.forObjectClassOrType(Activity.Builder.class, "activity");
        else
            return null;
    }

    /**
     * Method deserialize.
     * @param element JsonElement
     * @param type Type
     * @param context JsonDeserializationContext
     * @return ASObject 
     * @throws JsonParseException
     * @see com.google.gson.JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext) 
     **/
    public final ASObject deserialize(JsonElement element, Type type, JsonDeserializationContext context)
            throws JsonParseException {

        JsonObject obj = (JsonObject) element;
        ASObject.AbstractBuilder<?, ?> builder = null;
        Model propMap = null;
        TypeValue tv = null;

        if (knowsType(type)) {
            builder = builderFor(type);
            propMap = modelFor(type);
        } else {
            if (obj.has("objectType")) {
                tv = context.deserialize(obj.get("objectType"), TypeValue.class);
                @SuppressWarnings("rawtypes")
                Class<? extends ASObject.AbstractBuilder> _class = schema.builderForObjectTypeOrClass(tv.id(),
                        (Class) type);
                if (_class != null) {
                    propMap = schema.forObjectClassOrType(_class, tv.id());
                    if (!_class.isInterface()) {
                        try {
                            builder = _class.getConstructor(String.class).newInstance(tv.id());
                        } catch (Throwable t) {
                            try {
                                builder = _class.newInstance();
                                builder.set("objectType", tv);
                            } catch (Throwable t2) {
                                builder = Makers.object(tv);
                            }
                        }
                    } else
                        builder = Makers.object(tv);
                } else {
                    builder = Makers.object(tv);
                    propMap = schema.forObjectClassOrType(ASObject.Builder.class, tv.id());
                }
            } else {
                if (obj.has("verb") && (obj.has("actor") || obj.has("object") || obj.has("target"))) {
                    builder = activity();
                    propMap = schema.forObjectClassOrType(Activity.Builder.class, "activity");
                } else if (obj.has("items")) {
                    builder = collection();
                    propMap = schema.forObjectClassOrType(Collection.Builder.class, "collection");
                } else {
                    @SuppressWarnings("rawtypes")
                    Class<? extends ASObject.AbstractBuilder> _class = schema.builderFor((Class) type);
                    if (_class != null) {
                        if (!_class.isInterface()) {
                            try {
                                builder = _class.newInstance();
                            } catch (Throwable t) {
                                builder = object();
                            }
                        } else
                            builder = object();
                    }
                    if (builder == null)
                        builder = object(); // anonymous
                    propMap = schema.forObjectClass(builder.getClass());
                    propMap = propMap != null ? propMap : schema.forObjectClass(ASObject.Builder.class);
                }
            }
        }

        for (Entry<String, JsonElement> entry : obj.entrySet()) {
            String name = entry.getKey();
            if (name.equalsIgnoreCase("objectType"))
                continue;
            Class<?> _class = propMap.get(name);
            JsonElement val = entry.getValue();
            if (val.isJsonPrimitive())
                builder.set(name, _class != null ? context.deserialize(val, _class)
                        : primConverter.convert(val.getAsJsonPrimitive()));
            else if (val.isJsonArray()) {
                builder.set(name,
                        LinkValue.class.isAssignableFrom(_class != null ? _class : Object.class)
                                ? context.deserialize(val, LinkValue.class)
                                : convert(val.getAsJsonArray(), _class, context, builder()));
            } else if (val.isJsonObject())
                builder.set(name, context.deserialize(val, propMap.has(name) ? propMap.get(name) : ASObject.class));
        }
        return builder.get();

    }

    /**
     * Method convert.
     * @param arr JsonArray
     * @param _class Class<?>
     * @param context JsonDeserializationContext
     * @param list ImmutableList.Builder<Object>
     * @return ImmutableList<Object>
     */
    private ImmutableList<Object> convert(JsonArray arr, Class<?> _class, JsonDeserializationContext context,
            ImmutableList.Builder<Object> list) {
        processArray(arr, _class, context, list);
        return list.build();
    }

    /**
     * Method processArray.
     * @param arr JsonArray
     * @param _class Class<?>
     * @param context JsonDeserializationContext
     * @param list ImmutableList.Builder<Object>
     */
    private void processArray(JsonArray arr, Class<?> _class, JsonDeserializationContext context,
            ImmutableList.Builder<Object> list) {
        for (JsonElement mem : arr) {
            if (mem.isJsonPrimitive())
                list.add(_class != null ? context.deserialize(mem, _class)
                        : primConverter.convert(mem.getAsJsonPrimitive()));
            else if (mem.isJsonObject())
                list.add(context.deserialize(mem, _class != null ? _class : ASObject.class));
            else if (mem.isJsonArray())
                list.add(convert(mem.getAsJsonArray(), _class, context, builder()));
        }
    }

    public static final Converter<JsonPrimitive, Object> primConverter = new Converter<JsonPrimitive, Object>() {
        @Override
        protected JsonPrimitive doBackward(Object a) {
            if (a instanceof Boolean)
                return new JsonPrimitive((Boolean) a);
            else if (a instanceof Number)
                return new JsonPrimitive((Number) a);
            else
                return new JsonPrimitive(a.toString());
        }

        @Override
        protected Object doForward(JsonPrimitive b) {
            if (b.isBoolean())
                return b.getAsBoolean();
            else if (b.isNumber())
                return b.getAsNumber();
            else
                return b.getAsString();
        }
    };
}