package com.linkedin.databus2.core.container.request; /* * * Copyright 2013 LinkedIn Corp. All rights reserved * * 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. * */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; // WARNING: // Databus clients using clientRelayProtocol versions 3 or older do not handle // any extra fields in this object. // Clients using protocol versions 4 or above will ignore new fields added. public class RegisterResponseEntry { public final static String SOURCE_SCHEMAS_KEY = "sourceSchemas"; public final static String KEY_SCHEMAS_KEY = "keySchemas"; public static final String MODULE = RegisterResponseEntry.class.getName(); public static final Logger LOG = Logger.getLogger(MODULE); private long _id; private String _schema; private short _version; public RegisterResponseEntry(long id, short version, String schema) { super(); _id = id; _version = version; _schema = schema; } public RegisterResponseEntry() { this(0, (short)0,"N/A"); } public long getId() { return _id; } public void setId(long id) { _id = id; } public short getVersion() { return _version; } public void setVersion(short version) { _version = version; } public String getSchema() { return _schema; } public void setSchema(String schema) { _schema = schema; } public static Map<Long, List<RegisterResponseEntry>> createFromResponse(Map<String, List<Object>> responseMap, String hashKey, boolean optional) { List<Object> schemasList = responseMap.get(hashKey); if (optional) { if (schemasList == null) { LOG.info("/register response v4 has no '" + hashKey + "' entry"); } return null; } else { if (schemasList == null || schemasList.size() <= 0) { throw new RuntimeException("/register response v4 has no '" + hashKey + "' entry (or entry is empty)"); } } List<RegisterResponseEntry> sourcesSchemasList = reconstructSchemasList(schemasList); Map<Long, List<RegisterResponseEntry>> schemasMap = convertSchemaListToMap(sourcesSchemasList); return schemasMap; } // WARNING // Databus clients using clientRelayProtocol versions 3 or older handle the response to 'register' command by // directly serializing the response byte stream to a list of RegisterResponseEntry objects. // List<RegisterResponseEntry> schemas = // mapper.readValue(bodyStream, // new TypeReference<List<RegisterResponseEntry>>(){}); // The code below (versions 4+) looks only for fields known to the implementation. private static List<RegisterResponseEntry> reconstructSchemasList(List<Object> objectsList) { List<RegisterResponseEntry> schemasList = new ArrayList<RegisterResponseEntry>(); for (Object obj : objectsList) { // ObjectMapper encodes plain Object as LinkedHashMap (currently); must construct RRE manually boolean ok = false; if (obj instanceof Map) { @SuppressWarnings("unchecked") // just map Map<String, Object> map = (Map<String, Object>)obj; if (map.containsKey("id") && map.containsKey("version") && map.containsKey("schema")) { schemasList.add(new RegisterResponseEntry((Integer)map.get("id"), ((Integer)map.get("version")).shortValue(), (String)map.get("schema"))); ok = true; } } if (!ok) { throw new RuntimeException("/register response v4 schemas deserialization error: object type = " + obj.getClass().getName()); } } return schemasList; } /** * @return map from schema ID to a list of its schemas (typically different versions) */ public static Map<Long, List<RegisterResponseEntry>> convertSchemaListToMap(List<RegisterResponseEntry> schemasList) { HashMap<Long, List<RegisterResponseEntry>> schemasMap = new HashMap<Long, List<RegisterResponseEntry>>(schemasList.size() * 2); for (RegisterResponseEntry entry : schemasList) { List<RegisterResponseEntry> val = schemasMap.get(entry.getId()); if (null == val) { val = new ArrayList<RegisterResponseEntry>(); val.add(entry); schemasMap.put(entry.getId(), val); } else { val.add(entry); } } return schemasMap; } }