Java tutorial
/******************************************************************************* * 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) } }