com.getperka.flatpack.util.FlatPackEntityMerge Maven / Gradle / Ivy
package com.getperka.flatpack.util;
/*
* #%L
* FlatPack serialization code
* %%
* Copyright (C) 2012 Perka Inc.
* %%
* 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.
* #L%
*/
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import com.getperka.flatpack.Packer;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* A utility class to allow packed FlatPackEntities to be merged together without reifying them.
*
* @see Packer#pack(com.getperka.flatpack.FlatPackEntity)
*/
public class FlatPackEntityMerge {
public static JsonElement merge(Collection extends JsonElement> packs) {
return new FlatPackEntityMerge(packs).merge();
}
/**
* Merge several
*
* @param packs
* @return
*/
public static JsonElement merge(JsonElement... packs) {
return merge(Arrays.asList(packs));
}
private final Map> data = FlatPackCollections.mapForIteration();
private final Iterator extends JsonElement> iterator;
private FlatPackEntityMerge(Collection extends JsonElement> packs) {
iterator = packs.iterator();
}
/**
* Reassemble the type x uuid -> data map in {@link #data} into a single {@link JsonObject}.
*/
private JsonObject collateData() {
JsonObject toReturn = new JsonObject();
for (Map.Entry> entry : data.entrySet()) {
JsonArray array = new JsonArray();
for (JsonObject entity : entry.getValue().values()) {
array.add(entity);
}
toReturn.add(entry.getKey(), array);
}
return toReturn;
}
private JsonObject merge() {
JsonObject toReturn = new JsonObject();
JsonObject last = null;
while (iterator.hasNext()) {
last = iterator.next().getAsJsonObject();
mergeOnePack(last, toReturn);
}
// Copy only properties from the last entry
for (Map.Entry entry : last.entrySet()) {
toReturn.add(entry.getKey(), entry.getValue());
}
toReturn.add("data", collateData());
return toReturn;
}
/**
* Merges a map of type names to arrays of data values.
*/
private void mergeDataSection(JsonObject source) {
for (Map.Entry entry : source.entrySet()) {
String entityName = entry.getKey();
JsonArray entityArray = entry.getValue().getAsJsonArray();
Map map = data.get(entityName);
if (map == null) {
map = FlatPackCollections.mapForIteration();
data.put(entityName, map);
}
for (JsonElement entityData : entityArray) {
mergeEntityValues(entityData.getAsJsonObject(), map);
}
}
}
/**
* Merge the JsonObject for a single entity's data into a correlation map.
*/
private void mergeEntityValues(JsonObject source, Map map) {
UUID uuid = UUID.fromString(source.get("uuid").getAsString());
JsonObject dest = map.get(uuid);
if (dest == null) {
dest = new JsonObject();
map.put(uuid, dest);
}
for (Map.Entry entry : source.entrySet()) {
dest.add(entry.getKey(), entry.getValue());
}
}
private void mergeOnePack(JsonObject source, JsonObject toReturn) {
if (source.has("data")) {
mergeDataSection(source.get("data").getAsJsonObject());
}
}
}