blob: e5dfd0aceeb6f933795eb99f2e0dfce71902471f (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.document.idstring;
import com.yahoo.collections.MD5;
import com.yahoo.text.Utf8;
/**
* @author Magnar Nedland
*/
public class IdIdString extends IdString {
private final String type;
private String group;
private long location;
private boolean hasGroup;
private boolean hasNumber;
private static final int SIZE_OF_ID_AND_3_COLONS = 2 + 3; // "id:::"
private static final int MAX_LENGTH = IdString.MAX_LENGTH_EXCEPT_NAMESPACE_SPECIFIC - SIZE_OF_ID_AND_3_COLONS;
public static long makeLocation(String s) {
long result = 0;
byte[] md5sum = MD5.md5.get().digest(Utf8.toBytes(s));
for (int i = 0; i < 8; ++i) {
result |= (md5sum[i] & 0xFFL) << (8 * i);
}
return result;
}
/**
* Create an id scheme object.
* <code>doc:<namespace>:<documentType>:<key-value-pairs>:<namespaceSpecific></code>
*
* @param namespace The namespace of this document id.
* @param type The type of this document id.
* @param keyValues The key/value pairs of this document id.
* @param localId The namespace specific part.
*/
public IdIdString(String namespace, String type, String keyValues, String localId) {
super(Scheme.id, namespace, localId);
this.type = type;
boolean hasSetLocation = false;
if (namespace.length() + type.length() + keyValues.length() >= MAX_LENGTH) {
throw new IllegalArgumentException("Length of namespace(" + namespace.length() + ") + doctype(" + type.length() +
") + key/values(" + keyValues.length() +"), is longer than " + MAX_LENGTH);
}
for(String pair : keyValues.split(",")) {
int pos = pair.indexOf('=');
if (pos == -1) {
if (pair.equals("")) { // empty pair is ok
continue;
}
throw new IllegalArgumentException("Illegal key-value pair '" + pair + "'");
}
String key = pair.substring(0, pos);
String value = pair.substring(pos + 1);
switch(key) {
case "n":
if (hasSetLocation) {
throw new IllegalArgumentException("Illegal key combination in " + keyValues);
}
if (value.isEmpty()) {
throw new IllegalArgumentException("ID location value for 'n=' key is empty");
}
location = Long.parseLong(value);
hasSetLocation = true;
hasNumber = true;
break;
case "g":
if (hasSetLocation) {
throw new IllegalArgumentException("Illegal key combination in " + keyValues);
}
if (value.isEmpty()) {
throw new IllegalArgumentException("ID location value for 'g=' key is empty");
}
location = makeLocation(value);
hasSetLocation = true;
hasGroup = true;
group = value;
break;
default:
throw new IllegalArgumentException("Illegal key '" + key + "'");
}
}
if (!hasSetLocation) {
location = makeLocation(localId);
}
}
@Override
public long getLocation() {
return location;
}
@Override
public String getSchemeSpecific() {
if (hasGroup) {
return type + ":g=" + group + ":";
} else if (hasNumber) {
return type + ":n=" + location + ":";
} else {
return type + "::";
}
}
@Override
public boolean hasDocType() {
return true;
}
@Override
public String getDocType() {
return type;
}
@Override
public boolean hasGroup() {
return hasGroup;
}
@Override
public String getGroup() {
return group;
}
@Override
public boolean hasNumber() {
return hasNumber;
}
@Override
public long getNumber() {
return location;
}
}
|