com.ikanow.infinit.e.data_model.api.knowledge.DocumentPojoApiMap.java Source code

Java tutorial

Introduction

Here is the source code for com.ikanow.infinit.e.data_model.api.knowledge.DocumentPojoApiMap.java

Source

/*******************************************************************************
 * Copyright 2012 The Infinit.e Open Source Project
 * 
 * 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.ikanow.infinit.e.data_model.api.knowledge;

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

import org.bson.types.ObjectId;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
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.google.gson.JsonSerializer;
import com.ikanow.infinit.e.data_model.api.BaseApiPojo;
import com.ikanow.infinit.e.data_model.api.BasePojoApiMap;
import com.ikanow.infinit.e.data_model.store.MongoDbUtil;
import com.ikanow.infinit.e.data_model.store.document.DocumentPojo;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;

public class DocumentPojoApiMap implements BasePojoApiMap<DocumentPojo> {

    public GsonBuilder extendBuilder(GsonBuilder gp) {
        return gp.registerTypeAdapter(DocumentPojo.class, new DocumentPojoSerializer())
                .registerTypeAdapter(DocumentPojo.class, new DocumentPojoDeserializer());
    }

    // Tidy up document pojo from DB format to API format (few slight differences, see DocumentPojo)

    protected static class DocumentPojoSerializer implements JsonSerializer<DocumentPojo> {
        @Override
        public JsonElement serialize(DocumentPojo doc, Type typeOfT, JsonSerializationContext context) {
            // 1. On the document side: remove the internal index reference, other internal fields
            doc.setIndex(null);
            // (locs, months, timeRanges not stored in DB so no need to remove)

            // 1b. Also on the doc side: switch the update id and _id
            ObjectId updateId = doc.getUpdateId();
            if (null != updateId) {
                doc.setUpdateId(doc.getId()); // (store the old _id mostly for diagnosis)
                doc.setId(updateId); // this makes the _id field immutable across updates
            }

            // Everything else needs to be done on the JSON side:
            JsonElement je = BaseApiPojo.getDefaultBuilder().create().toJsonTree(doc, typeOfT);
            JsonObject jo = je.getAsJsonObject();
            JsonElement jetmp = null;
            // 2. Source title should be an array:
            jetmp = jo.get(DocumentPojo.source_);
            if (null != jetmp) {
                JsonArray ja = new JsonArray();
                ja.add(jetmp);
                jo.add(DocumentPojo.source_, ja);
            }
            // 3. Source keys should be an array:
            jetmp = jo.get(DocumentPojo.sourceKey_);
            // (also the <key>#<format> should be reduced back to <key>)
            if (null != jetmp) {
                String sourceKey = DocumentPojo.getSourceKey(jetmp.getAsString());
                jetmp = new JsonPrimitive(sourceKey);
                JsonArray ja = new JsonArray();
                ja.add(jetmp);
                jo.add(DocumentPojo.sourceKey_, ja);
            }
            // 4. Media types should be an array:
            jetmp = jo.get(DocumentPojo.mediaType_);
            if (null != jetmp) {
                JsonArray ja = new JsonArray();
                ja.add(jetmp);
                jo.add(DocumentPojo.mediaType_, ja);
            }
            // 5. Finally, CommunityId becomes an array
            jetmp = jo.get(DocumentPojo.communityId_);
            if (null != jetmp) {
                JsonArray ja = new JsonArray();
                ja.add(jetmp);
                jo.add(DocumentPojo.communityId_, ja);
            }
            return jo;
        }//TESTED (see DOC_API2 in TestCode)
    }

    // The same functionality as the above function but operates on the raw BasicDBObject
    // for performance

    public static void mapToApi(BasicDBObject doc) {
        // 1. (doc_index field)
        doc.remove(DocumentPojo.index_);
        // 2. (source title)
        String tmp = doc.getString(DocumentPojo.source_);
        if (null != tmp) {
            BasicDBList array = new BasicDBList();
            array.add(tmp);
            doc.put(DocumentPojo.source_, array);
        }
        // 3. (source key)
        tmp = DocumentPojo.getSourceKey(doc.getString(DocumentPojo.sourceKey_));
        if (null != tmp) {
            BasicDBList array = new BasicDBList();
            array.add(tmp);
            doc.put(DocumentPojo.sourceKey_, array);
        }
        // 4. (media type)
        tmp = doc.getString(DocumentPojo.mediaType_);
        if (null != tmp) {
            BasicDBList array = new BasicDBList();
            array.add(tmp);
            doc.put(DocumentPojo.mediaType_, array);
        }

    }//TESTED (see DOC_API1 in TestCode)

    protected static class DocumentPojoDeserializer implements JsonDeserializer<DocumentPojo> {
        public DocumentPojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            // We have converted many of the fields into arrays, we need to transform them back to single values
            // (we will have to discard the 2nd+ fields in each array - this call is only used for testing so we can live
            //  with that)

            JsonElement tmp = json.getAsJsonObject().get(DocumentPojo.source_);
            if ((null != tmp) && (tmp.isJsonArray())) {
                JsonArray tmpArray = tmp.getAsJsonArray();
                JsonElement singleVal = tmpArray.get(0);
                json.getAsJsonObject().add(DocumentPojo.source_, singleVal);
            }
            tmp = json.getAsJsonObject().get(DocumentPojo.sourceKey_);
            if ((null != tmp) && (tmp.isJsonArray())) {
                JsonArray tmpArray = tmp.getAsJsonArray();
                JsonElement singleVal = tmpArray.get(0); // (in array format, so must have already had #N/#NN stripped)
                json.getAsJsonObject().add(DocumentPojo.sourceKey_, singleVal);
            }
            tmp = json.getAsJsonObject().get(DocumentPojo.mediaType_);
            if ((null != tmp) && (tmp.isJsonArray())) {
                JsonArray tmpArray = tmp.getAsJsonArray();
                JsonElement singleVal = tmpArray.get(0);
                json.getAsJsonObject().add(DocumentPojo.mediaType_, singleVal);
            }
            tmp = json.getAsJsonObject().get(DocumentPojo.communityId_);
            if ((null != tmp) && (tmp.isJsonArray())) {
                JsonArray tmpArray = tmp.getAsJsonArray();
                JsonElement singleVal = tmpArray.get(0);
                json.getAsJsonObject().add(DocumentPojo.communityId_, singleVal);
            }
            // Finally sort out metadata...
            tmp = json.getAsJsonObject().get(DocumentPojo.metadata_);
            if (null != tmp) {
                json.getAsJsonObject().remove(DocumentPojo.metadata_);
            }

            DocumentPojo doc = BaseApiPojo.getDefaultBuilder().create().fromJson(json, DocumentPojo.class);

            // ...And add metadata back again...
            if (null != tmp) {
                JsonObject tmpMeta = tmp.getAsJsonObject();
                for (Entry<String, JsonElement> entry : tmpMeta.entrySet()) {
                    if (entry.getValue().isJsonArray()) {
                        doc.addToMetadata(entry.getKey(),
                                MongoDbUtil.encodeArray(entry.getValue().getAsJsonArray()));
                    } else {
                        BasicDBList dbl = new BasicDBList();
                        dbl.add(MongoDbUtil.encodeUnknown(entry.getValue()));
                        doc.addToMetadata(entry.getKey(), dbl);
                    }
                } //TOTEST            
            }

            // Finally handle updateId/_id swap
            ObjectId updateId = doc.getUpdateId();
            if (null != updateId) {
                doc.setUpdateId(doc.getId()); // (this is now the immutable _id)
                doc.setId(updateId); // this points to the _id in the DB
            }

            return doc;
        }//TESTED (by hand only, no formal record)      
    }
}