@Override
    public T decode(byte[] data) throws ConverterException {
        byte[] decompressedData;
        if (data[0] == 120) {
            decompressedData = decompress(data);
        } else {
            decompressedData = data;
        }

        Map<Integer, QualifiedValue<?>> idxLookup = new HashMap<>();
        T entity = createEntity();
        ByteArrayInputStream bin = new ByteArrayInputStream(decompressedData);
        CodedInputStream input = CodedInputStream.newInstance(bin);
        int tag;
        try {
            while ((tag = input.readTag()) != 0) {
                int field = WireFormat.getTagFieldNumber(tag);
                switch (field) {
                    case ID:
                        entity.setId(converterFactory.getIdEncoder().decode(input));
                        break;
                    case FIELD:
                        ByteString bf = input.readBytes();
                        readField(entity, bf.toByteArray(), idxLookup);
                        break;
                    case RELATION:
                        ByteString br = input.readBytes();
                        readRelation(entity, br.toByteArray(), idxLookup);
                        break;
                    default:
                        break;
                }
            }
        } catch (Exception e) {
            throw new ConverterException("Could not read entity from byte array!", e);
        } finally {
            try {
                bin.close();
            } catch (IOException e) {
                throw new RuntimeException("Could not close input stream!", e);
            }
        }
        return entity;
    }