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

Java tutorial

Introduction

Here is the source code for com.ibm.common.activitystreams.internal.GsonWrapper.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.gson.internal.bind.TypeAdapters.NUMBER;
import static com.ibm.common.activitystreams.internal.Adapters.DATE;
import static com.ibm.common.activitystreams.internal.Adapters.DATETIME;
import static com.ibm.common.activitystreams.internal.Adapters.NLV;
import static com.ibm.common.activitystreams.internal.Adapters.TABLE;
import static com.ibm.common.activitystreams.internal.Adapters.OPTIONAL;
import static com.ibm.common.activitystreams.internal.Adapters.ACTIONS;
import static com.ibm.common.activitystreams.internal.Adapters.DURATION;
import static com.ibm.common.activitystreams.internal.Adapters.INTERVAL;
import static com.ibm.common.activitystreams.internal.Adapters.ITERABLE;
import static com.ibm.common.activitystreams.internal.Adapters.MIMETYPE;
import static com.ibm.common.activitystreams.internal.Adapters.MULTIMAP;
import static com.ibm.common.activitystreams.internal.Adapters.RANGE;
import static com.ibm.common.activitystreams.internal.Adapters.PERIOD;
import static com.ibm.common.activitystreams.internal.Adapters.forEnum;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.ReadableDuration;
import org.joda.time.ReadableInterval;
import org.joda.time.ReadablePeriod;

import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.Range;
import com.google.common.collect.Table;
import com.google.common.net.MediaType;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.LazilyParsedNumber;
import com.ibm.common.activitystreams.ASObject;
import com.ibm.common.activitystreams.ActionsValue;
import com.ibm.common.activitystreams.Activity;
import com.ibm.common.activitystreams.Collection;
import com.ibm.common.activitystreams.LinkValue;
import com.ibm.common.activitystreams.NLV;
import com.ibm.common.activitystreams.TypeValue;
import com.ibm.common.activitystreams.Writable;

/**
 * @author james
 * @version $Revision: 1.0 $
 */
public final class GsonWrapper {

    /**
     * Method make.
        
     * @return Builder */
    public static final Builder make() {
        return new Builder();
    }

    /**
     * @author james
     * @version $Revision: 1.0 $
     */
    public static final class Builder implements Supplier<GsonWrapper> {

        private String charset = "UTF-8";
        private boolean pretty;
        private Schema schema = null; // default
        private ImmutableList.Builder<AdapterEntry<?>> adapters = ImmutableList.builder();

        /**
         * Method charset.
         * @param charset String
            
         * @return Builder */
        public Builder charset(String charset) {
            this.charset = charset;
            return this;
        }

        /**
         * Method schema.
         * @param schema Schema
            
         * @return Builder */
        public Builder schema(Schema schema) {
            this.schema = schema;
            return this;
        }

        /**
         * Method adapter.
         * @param type Class<? extends T>
         * @param adapter Adapter<T>
            
         * @return Builder */
        public <T> Builder adapter(Class<? extends T> type, Adapter<T> adapter) {
            return adapter(type, adapter, false);
        }

        /**
         * Method adapter.
         * @param type Class<? extends T>
         * @param adapter Adapter<T>
         * @param hier boolean
            
         * @return Builder */
        public <T> Builder adapter(Class<? extends T> type, Adapter<T> adapter, boolean hier) {
            adapters.add(new AdapterEntry<T>(type, adapter, hier));
            return this;
        }

        /**
         * Method prettyPrint.
         * @param on boolean
            
         * @return Builder */
        public Builder prettyPrint(boolean on) {
            this.pretty = on;
            return this;
        }

        /**
         * Method prettyPrint.
            
         * @return Builder */
        public Builder prettyPrint() {
            return prettyPrint(true);
        }

        /**
         * Method get.
            
            
         * @return GsonWrapper * @see com.google.common.base.Supplier#get() */
        public GsonWrapper get() {
            return new GsonWrapper(this);
        }

    }

    /**
     * @author james
     * @version $Revision: 1.0 $
     */
    private final static class AdapterEntry<T> {
        private final Class<? extends T> type;
        private final Adapter<T> adapter;
        private final boolean hier;

        /**
         * Constructor for AdapterEntry.
         * @param type Class<? extends T>
         * @param adapter Adapter<T>
         * @param hier boolean
         */
        AdapterEntry(Class<? extends T> type, Adapter<T> adapter, boolean hier) {
            this.type = type;
            this.adapter = adapter;
            this.hier = hier;
        }
    }

    private final Gson gson;
    private final String charset;

    /**
     * Constructor for GsonWrapper.
     * @param builder Builder
     */
    protected GsonWrapper(Builder builder) {
        Schema schema = builder.schema != null ? builder.schema : Schema.make().get();
        ASObjectAdapter base = new ASObjectAdapter(schema);
        GsonBuilder b = initGsonBuilder(builder, schema, base, builder.adapters.build());
        if (builder.pretty)
            b.setPrettyPrinting();
        this.gson = b.create();
        this.charset = builder.charset;
    }

    /**
     * Method initGsonBuilder.
     * @param builder Builder
        
     * @return GsonBuilder */
    private static GsonBuilder initGsonBuilder(Builder builder, Schema schema, ASObjectAdapter base,
            Iterable<AdapterEntry<?>> adapters) {

        GsonBuilder gson = new GsonBuilder()
                .registerTypeHierarchyAdapter(TypeValue.class, new TypeValueAdapter(schema))
                .registerTypeHierarchyAdapter(LinkValue.class, new LinkValueAdapter(schema))
                .registerTypeHierarchyAdapter(Iterable.class, ITERABLE)
                .registerTypeHierarchyAdapter(ASObject.class, base)
                .registerTypeHierarchyAdapter(Collection.class, base)
                .registerTypeHierarchyAdapter(Activity.class, base).registerTypeHierarchyAdapter(NLV.class, NLV)
                .registerTypeHierarchyAdapter(ActionsValue.class, ACTIONS)
                .registerTypeHierarchyAdapter(Optional.class, OPTIONAL)
                .registerTypeHierarchyAdapter(Range.class, RANGE).registerTypeHierarchyAdapter(Table.class, TABLE)
                .registerTypeHierarchyAdapter(LazilyParsedNumber.class, NUMBER)
                .registerTypeHierarchyAdapter(LazilyParsedNumberComparable.class, NUMBER)
                .registerTypeHierarchyAdapter(ReadableDuration.class, DURATION)
                .registerTypeHierarchyAdapter(ReadablePeriod.class, PERIOD)
                .registerTypeHierarchyAdapter(ReadableInterval.class, INTERVAL)
                .registerTypeAdapter(Activity.Status.class, forEnum(Activity.Status.class, Activity.Status.OTHER))
                .registerTypeAdapter(Date.class, DATE).registerTypeAdapter(DateTime.class, DATETIME)
                .registerTypeAdapter(MediaType.class, MIMETYPE)
                .registerTypeHierarchyAdapter(Multimap.class, MULTIMAP);

        for (AdapterEntry<?> entry : adapters) {
            if (entry.hier)
                gson.registerTypeHierarchyAdapter(entry.type, entry.adapter != null ? entry.adapter : base);
            else
                gson.registerTypeAdapter(entry.type, entry.adapter != null ? entry.adapter : base);
        }

        return gson;

    }

    /**
     * Method write.
     * @param w Writable
     * @param out OutputStream
     */
    public void write(Writable w, OutputStream out) {
        try {
            OutputStreamWriter wout = new OutputStreamWriter(out, charset);
            gson.toJson(w, wout);
            wout.flush();
        } catch (Throwable t) {
            throw Throwables.propagate(t);
        }
    }

    /**
     * Method write.
     * @param w Writable
     * @param out Writer
     */
    public void write(Writable w, Writer out) {
        gson.toJson(w, out);
    }

    /**
     * Method write.
     * @param w Writable
        
     * @return String */
    public String write(Writable w) {
        StringWriter sw = new StringWriter();
        write(w, sw);
        return sw.toString();
    }

    /**
     * Method readAs.
     * @param in InputStream
     * @param type Class<? extends A>
        
     * @return A */
    public <A extends ASObject> A readAs(InputStream in, Class<? extends A> type) {
        try {
            return readAs(new InputStreamReader(in, charset), type);
        } catch (Throwable t) {
            throw Throwables.propagate(t);
        }
    }

    /**
     * Method readAs.
     * @param in Reader
     * @param type Class<? extends A>
        
     * @return A */
    public <A extends ASObject> A readAs(Reader in, Class<? extends A> type) {
        return (A) gson.fromJson(in, type);
    }
}