1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.accumulo.core.iterators.conf;
18
19 import java.util.Collection;
20 import java.util.HashSet;
21 import java.util.Set;
22
23 import org.apache.accumulo.core.data.Key;
24 import org.apache.accumulo.core.iterators.conf.ColumnUtil.ColFamHashKey;
25 import org.apache.accumulo.core.iterators.conf.ColumnUtil.ColHashKey;
26 import org.apache.accumulo.core.util.Pair;
27 import org.apache.hadoop.io.Text;
28
29 public class ColumnSet {
30 private Set<ColFamHashKey> objectsCF;
31 private Set<ColHashKey> objectsCol;
32
33 private ColHashKey lookupCol = new ColHashKey();
34 private ColFamHashKey lookupCF = new ColFamHashKey();
35
36 public ColumnSet() {
37 objectsCF = new HashSet<ColFamHashKey>();
38 objectsCol = new HashSet<ColHashKey>();
39 }
40
41 public ColumnSet(Collection<String> objectStrings) {
42 this();
43
44 for (String column : objectStrings) {
45 Pair<Text,Text> pcic = ColumnSet.decodeColumns(column);
46
47 if (pcic.getSecond() == null) {
48 add(pcic.getFirst());
49 } else {
50 add(pcic.getFirst(), pcic.getSecond());
51 }
52 }
53 }
54
55 protected void add(Text colf) {
56 objectsCF.add(new ColFamHashKey(new Text(colf)));
57 }
58
59 protected void add(Text colf, Text colq) {
60 objectsCol.add(new ColHashKey(colf, colq));
61 }
62
63 public boolean contains(Key key) {
64
65 if (objectsCol.size() > 0) {
66 lookupCol.set(key);
67 if (objectsCol.contains(lookupCol))
68 return true;
69 }
70
71
72 if (objectsCF.size() > 0) {
73 lookupCF.set(key);
74 return objectsCF.contains(lookupCF);
75 }
76
77 return false;
78 }
79
80 public boolean isEmpty() {
81 return objectsCol.size() == 0 && objectsCF.size() == 0;
82 }
83
84 public static String encodeColumns(Text columnFamily, Text columnQualifier) {
85 StringBuilder sb = new StringBuilder();
86
87 encode(sb, columnFamily);
88 if (columnQualifier != null) {
89 sb.append(':');
90 encode(sb, columnQualifier);
91 }
92
93 return sb.toString();
94 }
95
96 static void encode(StringBuilder sb, Text t) {
97 for (int i = 0; i < t.getLength(); i++) {
98 int b = (0xff & t.getBytes()[i]);
99
100
101 if ((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '_' || b == '-') {
102 sb.append((char) b);
103 } else {
104 sb.append('%');
105 sb.append(String.format("%02x", b));
106 }
107 }
108 }
109
110 public static boolean isValidEncoding(String enc) {
111 for (char c : enc.toCharArray()) {
112 boolean validChar = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == ':' || c == '%';
113 if (!validChar)
114 return false;
115 }
116
117 return true;
118 }
119
120 public static Pair<Text,Text> decodeColumns(String columns) {
121 if (!isValidEncoding(columns))
122 throw new IllegalArgumentException("Invalid encoding " + columns);
123
124 String[] cols = columns.split(":");
125
126 if (cols.length == 1) {
127 return new Pair<Text,Text>(decode(cols[0]), null);
128 } else if (cols.length == 2) {
129 return new Pair<Text,Text>(decode(cols[0]), decode(cols[1]));
130 } else {
131 throw new IllegalArgumentException(columns);
132 }
133 }
134
135 static Text decode(String s) {
136 Text t = new Text();
137
138 byte[] sb = s.getBytes();
139
140
141 for (int i = 0; i < sb.length; i++) {
142 if (sb[i] != '%') {
143 t.append(new byte[] {sb[i]}, 0, 1);
144 } else {
145 byte hex[] = new byte[] {sb[++i], sb[++i]};
146 String hs = new String(hex);
147 int b = Integer.parseInt(hs, 16);
148 t.append(new byte[] {(byte) b}, 0, 1);
149 }
150 }
151
152 return t;
153 }
154 }