/**
* Copyright 2013 Netflix, 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.
*/
package com.netflix.aegisthus.tools;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.pig.data.DataByteArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
/**
* Read and write Aegisthus Json format.
*/
public class AegisthusSerializer {
private static final Logger LOG = LoggerFactory.getLogger(AegisthusSerializer.class);
public static String DELETEDAT = "DELETEDAT";
public static String KEY = "$$KEY$$";
protected static JsonFactory jsonFactory = new JsonFactory();
static {
jsonFactory.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
}
public Object type(String value) {
return value;
}
public Map<String, Object> deserialize(String data) throws IOException {
try {
Map<String, Object> map = new LinkedHashMap<String, Object>();
JsonParser jp = jsonFactory.createJsonParser(data);
jp.nextToken(); // Object
jp.nextToken(); // key
map.put(KEY, new DataByteArray(jp.getCurrentName().getBytes()));
jp.nextToken(); // object
while (jp.nextToken() != JsonToken.END_OBJECT) {
String field = jp.getCurrentName();
if (DELETEDAT.equals(field.toUpperCase())) {
jp.nextToken();
map.put(DELETEDAT, jp.getLongValue());
} else {
jp.nextToken();
while (jp.nextToken() != JsonToken.END_ARRAY) {
List<Object> cols = new ArrayList<Object>();
jp.nextToken();
String name = jp.getText();
cols.add(name);
jp.nextToken();
cols.add(new DataByteArray(jp.getText().getBytes()));
jp.nextToken();
cols.add(jp.getLongValue());
if (jp.nextToken() != JsonToken.END_ARRAY) {
String status = jp.getText();
cols.add(status);
if ("e".equals(status)) {
jp.nextToken();
cols.add(jp.getLongValue());
jp.nextToken();
cols.add(jp.getLongValue());
} else if ("c".equals(status)) {
jp.nextToken();
cols.add(jp.getLongValue());
}
jp.nextToken();
}
map.put(name, cols);
}
}
}
return map;
} catch (IOException e) {
LOG.error(data);
throw e;
}
}
protected static void insertKey(StringBuilder sb, Object value) {
sb.append("\"");
sb.append(value);
sb.append("\": ");
}
protected static void serializeColumns(StringBuilder sb, Map<String, Object> columns) {
int count = 0;
for (Map.Entry<String, Object> e : columns.entrySet()) {
if (count++ > 0) {
sb.append(", ");
}
@SuppressWarnings("unchecked")
List<Object> list = (List<Object>) e.getValue();
sb.append("[");
sb.append("\"").append(((String) list.get(0)).replace("\\", "\\\\").replace("\"", "\\\"")).append("\"").append(",");
sb.append("\"").append(list.get(1)).append("\"").append(",");
sb.append(list.get(2));
if (list.size() > 3) {
sb.append(",").append("\"").append(list.get(3)).append("\"");
}
for (int i = 4; i < list.size(); i++) {
sb.append(",").append(list.get(i));
}
sb.append("]");
}
}
public static String serialize(Map<String, Object> data) {
StringBuilder str = new StringBuilder();
str.append("{");
insertKey(str, data.remove(KEY));
str.append("{");
insertKey(str, "deletedAt");
str.append(data.remove(DELETEDAT));
str.append(", ");
insertKey(str, "columns");
str.append("[");
serializeColumns(str, data);
str.append("]");
str.append("}}");
return str.toString();
}
}