/*
* Copyright 2011 Facebook, Inc.
*
* 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.facebook.tsdb.tsdash.server.model;
import java.io.IOException;
import java.util.Comparator;
import com.facebook.tsdb.tsdash.server.data.hbase.IDMap;
import com.facebook.tsdb.tsdash.server.data.hbase.IDNotFoundException;
public class Tag {
public ID keyID;
public ID valueID;
public String key = "";
public String value = "";
private static Comparator<Tag> keyComparator = new Comparator<Tag>() {
@Override
public int compare(Tag t1, Tag t2) {
return t1.keyID.compareTo(t2.keyID);
}
};
private static Comparator<Tag> keyValueComparator = new Comparator<Tag>() {
@Override
public int compare(Tag t1, Tag t2) {
int keyCmp = t1.keyID.compareTo(t2.keyID);
if (keyCmp == 0) {
return t1.valueID.compareTo(t2.valueID);
}
return keyCmp;
}
};
private static class TagsArrayComparator implements Comparator<TagsArray> {
private int[] map = new int[0];
private void ensureMapLength(int length) {
if (length > map.length) {
map = new int[length];
}
}
@Override
public int compare(TagsArray tlist1, TagsArray tlist2) {
// first set mapping between the two lists
TagsArray shortList = tlist1;
TagsArray longList = tlist2;
if (tlist1.length() > tlist2.length()) {
shortList = tlist2;
longList = tlist1;
}
ensureMapLength(shortList.length());
// do the mapping
for (int i = 0; i < shortList.length(); i++) {
map[i] = longList.binarySearch(shortList.getOrdered(i));
}
for (int i = 0; i < shortList.length(); i++) {
if (map[i] < 0) {
// skip this tag, as it doesn't exist in the other list
continue;
}
int tagCmp = shortList.getOrdered(i).valueID.compareTo(longList
.get(map[i]).valueID);
if (tagCmp != 0) {
return tagCmp;
}
}
return 0;
}
};
private void loadStringFields(IDMap idMap) {
try {
key = this.keyID.isNull() ? "NULL" : idMap.getTag(this.keyID);
value = this.valueID.isNull() ? "NULL" : idMap
.getTagValue(this.valueID);
} catch (Exception e) {
e.printStackTrace();
}
}
public Tag(byte[] rawKeyID, byte[] rawValueID, IDMap idMap) {
this.keyID = new ID(rawKeyID);
this.valueID = new ID(rawValueID);
loadStringFields(idMap);
}
public Tag(ID keyID, ID valueID, IDMap idMap) {
this.keyID = keyID;
this.valueID = valueID;
loadStringFields(idMap);
}
public Tag(String key, String value, IDMap idMap) throws IOException,
IDNotFoundException {
this.key = key;
this.value = value;
this.keyID = idMap.getTagID(key);
this.valueID = idMap.getTagValueID(value);
}
public Tag(String tagName, IDMap idMap) throws IOException,
IDNotFoundException {
this.key = tagName;
this.keyID = idMap.getTagID(tagName);
}
public static Comparator<TagsArray> arrayComparator() {
// we need to create a separate instance because the comparator is
// not thread safe, as it needs the temporary storage array
return new TagsArrayComparator();
}
@Override
public String toString() {
return "(" + key + "[" + keyID + "]:" + value + "[" + valueID + "])";
}
public static String join(String glue, Tag[] tags) {
String ret = "";
for (int i = 0; i < tags.length; i++) {
if (i > 0) {
ret += glue;
}
ret += tags[i].toString();
}
return ret;
}
public String toHexString() {
return keyID.toHexString() + valueID.toHexString();
}
public static Comparator<Tag> keyComparator() {
return keyComparator;
}
public static Comparator<Tag> keyValueComparator() {
return keyValueComparator;
}
}