/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.hadoop.hive.serde2.dynamic_type; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.hadoop.hive.serde2.SerDeException; import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.thrift.WriteNullsProtocol; import org.apache.thrift.TException; import org.apache.thrift.protocol.TMap; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TType; /** * DynamicSerDeTypeMap. * */ public class DynamicSerDeTypeMap extends DynamicSerDeTypeBase { @Override public boolean isPrimitive() { return false; } @Override public boolean isMap() { return true; } // production is: Map<FieldType(),FieldType()> private final byte FD_KEYTYPE = 0; private final byte FD_VALUETYPE = 1; // returns Map<?,?> @Override public Class getRealType() { try { Class c = getKeyType().getRealType(); Class c2 = getValueType().getRealType(); Object o = c.newInstance(); Object o2 = c2.newInstance(); Map<?, ?> l = Collections.singletonMap(o, o2); return l.getClass(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } public DynamicSerDeTypeMap(int i) { super(i); } public DynamicSerDeTypeMap(thrift_grammar p, int i) { super(p, i); } public DynamicSerDeTypeBase getKeyType() { return ((DynamicSerDeFieldType) jjtGetChild(FD_KEYTYPE)).getMyType(); } public DynamicSerDeTypeBase getValueType() { return ((DynamicSerDeFieldType) jjtGetChild(FD_VALUETYPE)).getMyType(); } @Override public String toString() { return "map<" + getKeyType().toString() + "," + getValueType().toString() + ">"; } @Override public Map<Object, Object> deserialize(Object reuse, TProtocol iprot) throws SerDeException, TException, IllegalAccessException { HashMap<Object, Object> deserializeReuse; if (reuse != null) { deserializeReuse = (HashMap<Object, Object>) reuse; deserializeReuse.clear(); } else { deserializeReuse = new HashMap<Object, Object>(); } TMap themap = iprot.readMapBegin(); if (themap == null) { return null; } // themap might be reused by the Protocol. int mapSize = themap.size; for (int i = 0; i < mapSize; i++) { Object key = getKeyType().deserialize(null, iprot); Object value = getValueType().deserialize(null, iprot); deserializeReuse.put(key, value); } // in theory, the below call isn't needed in non thrift_mode, but let's not // get too crazy iprot.readMapEnd(); return deserializeReuse; } TMap serializeMap = null; @Override public void serialize(Object o, ObjectInspector oi, TProtocol oprot) throws TException, SerDeException, NoSuchFieldException, IllegalAccessException { DynamicSerDeTypeBase keyType = getKeyType(); DynamicSerDeTypeBase valueType = getValueType(); WriteNullsProtocol nullProtocol = (oprot instanceof WriteNullsProtocol) ? (WriteNullsProtocol) oprot : null; assert (oi.getCategory() == ObjectInspector.Category.MAP); MapObjectInspector moi = (MapObjectInspector) oi; ObjectInspector koi = moi.getMapKeyObjectInspector(); ObjectInspector voi = moi.getMapValueObjectInspector(); Map<?, ?> map = moi.getMap(o); serializeMap = new TMap(keyType.getType(), valueType.getType(), map.size()); oprot.writeMapBegin(serializeMap); for (Object element : map.entrySet()) { Map.Entry it = (Map.Entry) element; Object key = it.getKey(); Object value = it.getValue(); keyType.serialize(key, koi, oprot); if (value == null) { assert (nullProtocol != null); nullProtocol.writeNull(); } else { valueType.serialize(value, voi, oprot); } } // in theory, the below call isn't needed in non thrift_mode, but let's not // get too crazy oprot.writeMapEnd(); } @Override public byte getType() { return TType.MAP; } };