package com.linkedin.camus.schemaregistry;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
/**
* This is an in-memory implementation of a SchemaRegistry. It has no
* persistence. If you wish to make schema IDs match between executions, you
* must issue register calls in the same order each time, as the schema IDs are
* a long that's incremented on every register call.
*
* @param <S>
* The type of the schema that this registry manages.
*/
public class MemorySchemaRegistry<S> implements SchemaRegistry<S> {
private final Map<MemorySchemaRegistryTuple, S> schemasById;
private final Map<String, MemorySchemaRegistryTuple> latest;
private final AtomicLong ids;
public void init(Properties props) {
}
public MemorySchemaRegistry() {
this.schemasById = new ConcurrentHashMap<MemorySchemaRegistryTuple, S>();
this.latest = new ConcurrentHashMap<String, MemorySchemaRegistryTuple>();
this.ids = new AtomicLong(0);
}
@Override
public String register(String topic, S schema) {
long id = ids.incrementAndGet();
MemorySchemaRegistryTuple tuple = new MemorySchemaRegistryTuple(topic, id);
schemasById.put(tuple, schema);
latest.put(topic, tuple);
return Long.toString(id);
}
@Override
public S getSchemaByID(String topicName, String idStr) {
try {
S schema = schemasById.get(new MemorySchemaRegistryTuple(topicName, Long.parseLong(idStr)));
if (schema == null) {
throw new SchemaNotFoundException();
}
return schema;
} catch (NumberFormatException e) {
throw new SchemaNotFoundException("Supplied a non-long id string.", e);
}
}
@Override
public SchemaDetails<S> getLatestSchemaByTopic(String topicName) {
MemorySchemaRegistryTuple tuple = latest.get(topicName);
if (tuple == null) {
throw new SchemaNotFoundException();
}
S schema = schemasById.get(tuple);
if (schema == null) {
throw new SchemaNotFoundException();
}
return new SchemaDetails<S>(topicName, Long.toString(tuple.getId()), schema);
}
public class MemorySchemaRegistryTuple {
private final String topicName;
private final long id;
public MemorySchemaRegistryTuple(String topicName, long id) {
this.topicName = topicName;
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + ((topicName == null) ? 0 : topicName.hashCode());
return result;
}
public String getTopicName() {
return topicName;
}
public long getId() {
return id;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MemorySchemaRegistryTuple other = (MemorySchemaRegistryTuple) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (id != other.id)
return false;
if (topicName == null) {
if (other.topicName != null)
return false;
} else if (!topicName.equals(other.topicName))
return false;
return true;
}
private MemorySchemaRegistry getOuterType() {
return MemorySchemaRegistry.this;
}
@Override
public String toString() {
return "MemorySchemaRegistryTuple [topicName=" + topicName + ", id=" + id + "]";
}
}
}