package com.netflix.aegisthus.io.writable;
import com.google.common.collect.ComparisonChain;
import com.netflix.Aegisthus;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.TypeParser;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import java.nio.ByteBuffer;
import java.util.Comparator;
public class AegisthusKeySortingComparator extends WritableComparator implements Configurable {
private AbstractType<ByteBuffer> columnNameConverter;
private Configuration conf;
private boolean legacyColumnNameFormatting;
private boolean sortColumnsByName;
private AegisthusKey key1 = new AegisthusKey();
private AegisthusKey key2 = new AegisthusKey();
public AegisthusKeySortingComparator() {
super(AegisthusKey.class, false);
}
public static String legacyColumnNameFormat(String columnName) {
return columnName.replaceAll("[\\s\\p{Cntrl}]", " ").replace("\\", "\\\\").replace("\"", "\\\"");
}
@Override
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
Comparator<ByteBuffer> nameComparator = columnNameConverter;
if (sortColumnsByName) {
nameComparator = new Comparator<ByteBuffer>() {
@Override
public int compare(ByteBuffer o1, ByteBuffer o2) {
if (o1 == null || o2 == null) {
return ComparisonChain.start().compare(o1, o2).result();
}
String c1Name = columnNameConverter.getString(o1);
String c2Name = columnNameConverter.getString(o2);
if (legacyColumnNameFormatting) {
c1Name = legacyColumnNameFormat(c1Name);
c2Name = legacyColumnNameFormat(c2Name);
}
return c1Name.compareTo(c2Name);
}
};
}
key1.readFields(b1, s1, l1);
key2.readFields(b2, s2, l2);
return key1.compareTo(key2, nameComparator);
}
@Override
public Configuration getConf() {
return conf;
}
@Override
public void setConf(Configuration conf) {
this.conf = conf;
String columnType = conf.get(Aegisthus.Feature.CONF_COLUMNTYPE, "BytesType");
legacyColumnNameFormatting = conf.getBoolean(Aegisthus.Feature.CONF_LEGACY_COLUMN_NAME_FORMATTING, false);
sortColumnsByName = conf.getBoolean(Aegisthus.Feature.CONF_SORT_COLUMNS_BY_NAME, false);
try {
//noinspection unchecked
columnNameConverter = (AbstractType<ByteBuffer>) TypeParser.parse(columnType);
} catch (SyntaxException | ConfigurationException e) {
throw new RuntimeException(e);
}
}
}