/**
* Copyright [2011] [Datasalt Systems S.L.]
*
* 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.
*/
package com.datasalt.utils.io;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.io.WritableUtils;
import org.apache.hadoop.mapreduce.Partitioner;
@SuppressWarnings({ "rawtypes" })
public class TextPairWritable implements WritableComparable<TextPairWritable> {
private Text first;
private Text second;
public TextPairWritable() {
first = new Text();
second = new Text();
}
public TextPairWritable(String first, String second) {
this();
this.first.set(first);
this.second.set(second);
}
public void readFields(DataInput input) throws IOException {
first.readFields(input);
second.readFields(input);
}
public void write(DataOutput output) throws IOException {
first.write(output);
second.write(output);
}
public int compareTo(TextPairWritable that) {
int compareTo = this.first.compareTo(((TextPairWritable) that).getFirst());
int firstComparison = compareTo;
return (firstComparison != 0) ? firstComparison : this.getSecond()
.compareTo(((TextPairWritable) that).getSecond());
}
public static class Comparator extends WritableComparator {
public Comparator() {
super(TextPairWritable.class);
}
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
int comparison;
int length1, length2;
int offset1,offset2;
try {
length1 = readVInt(b1, s1);
length2 = readVInt(b2, s2);
offset1 = s1 + WritableUtils.decodeVIntSize(b1[s1]);
offset2 = s2 + WritableUtils.decodeVIntSize(b2[s2]);
comparison = compareBytes(b1,offset1,
length1, b2, offset2, length2);
if (comparison != 0) {
return comparison;
} else {
offset1 = offset1 + length1;
offset2 = offset2 + length2;
length1 = readVInt(b1,offset1);
length2 = readVInt(b2,offset2);
comparison = compareBytes(b1,
offset1 + WritableUtils.decodeVIntSize(b1[offset1]), length1, b2, offset2 + WritableUtils.decodeVIntSize(b2[offset2]), length2);
return comparison;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static class FirstStringComparator extends WritableComparator {
public FirstStringComparator() {
super(TextPairWritable.class);
}
public int compare(WritableComparable a, WritableComparable b) {
return ((TextPairWritable) a).first.compareTo(((TextPairWritable) b)
.getFirst());
}
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
try {
int comparison, textOffset1, textOffset2;
int length1 = readVInt(b1, s1); // text length coded in binary
int length2 = readVInt(b2, s2);
textOffset1 = WritableUtils.decodeVIntSize(b1[s1]);
textOffset2 = WritableUtils.decodeVIntSize(b2[s2]);
comparison = compareBytes(b1, s1 + textOffset1, length1, b2, s2
+ textOffset2, length2);
return comparison;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static class FirstStringPartitioner extends
Partitioner<TextPairWritable, Object> {
public int getPartition(TextPairWritable key, Object value,
int numReduceTasks) {
return (key.getFirst().toString().hashCode() & Integer.MAX_VALUE)
% numReduceTasks;
}
}
static { // register this comparator
WritableComparator.define(TextPairWritable.class, new Comparator());
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("{").append(first).append(",").append(second).append("}");
return builder.toString();
}
public Text getFirst() {
return first;
}
public void setFirst(String first) {
this.first.set(first);
}
public Text getSecond() {
return second;
}
public void setSecond(String second) {
this.second.set(second);
}
}