1 package org
.argeo
.api
.gcr
;
3 import static java
.nio
.charset
.StandardCharsets
.UTF_8
;
5 import java
.nio
.charset
.StandardCharsets
;
6 import java
.util
.Collections
;
8 import java
.util
.Objects
;
9 import java
.util
.TreeMap
;
10 import java
.util
.UUID
;
12 import javax
.xml
.XMLConstants
;
13 import javax
.xml
.namespace
.NamespaceContext
;
14 import javax
.xml
.namespace
.QName
;
17 * A {@link QName} which MUST have prefix and whose {@link #toString()} method
18 * returns the prefixed form (prefix:localPart).
20 public class ContentName
extends QName
{
21 private static final long serialVersionUID
= 5722920985400306100L;
22 public final static UUID NIL_UUID
= UUID
.fromString("00000000-0000-0000-0000-000000000000");
24 * The UUID v3 of http://www.w3.org/2000/xmlns/ within the standard DNS
25 * namespace, to be used as a base for the namespaces.
27 * @see https://www.w3.org/TR/xml-names/#ns-decl
29 // uuidgen --md5 --namespace @dns --name http://www.w3.org/2000/xmlns/
30 // NOTE : must be declared before default namespaces
31 public final static UUID XMLNS_UUID
= UUID
.fromString("4b352aad-ba1c-3139-b9d3-41e5816f6088");
32 // uuidgen --md5 --namespace 4b352aad-ba1c-3139-b9d3-41e5816f6088 --name ""
33 public final static UUID NULL_NS_UUID
= UUID
.fromString("f07726e3-99c8-3178-b758-a86ed41f300d");
35 private final static Map
<String
, UUID
> namespaceUuids
= Collections
.synchronizedMap(new TreeMap
<>());
36 private final static Map
<String
, UUID
> nameUuids
= Collections
.synchronizedMap(new TreeMap
<>());
39 assert NULL_NS_UUID
.equals(nameUUIDv3(XMLNS_UUID
, XMLConstants
.NULL_NS_URI
.getBytes(UTF_8
)));
42 // private final UUID uuid;
44 public ContentName(String namespaceURI
, String localPart
, NamespaceContext nsContext
) {
45 this(namespaceURI
, localPart
, nsContext
.getPrefix(namespaceURI
));
48 protected ContentName(String namespaceURI
, String localPart
, String prefix
) {
49 super(namespaceURI
, localPart
, prefix
);
51 throw new IllegalArgumentException("Prefix annot be null");
54 public ContentName(String localPart
) {
55 this(XMLConstants
.NULL_NS_URI
, localPart
, XMLConstants
.DEFAULT_NS_PREFIX
);
58 public ContentName(QName qName
, NamespaceContext nsContext
) {
59 this(qName
.getNamespaceURI(), qName
.getLocalPart(), nsContext
);
62 public String
toQNameString() {
63 return super.toString();
66 public String
toPrefixedString() {
67 return toPrefixedString(this);
75 public String
toString() {
76 return toPrefixedString();
80 protected Object
clone() throws CloneNotSupportedException
{
81 return new ContentName(getNamespaceURI(), getLocalPart(), getPrefix());
84 public static String
toPrefixedString(QName name
) {
85 String prefix
= name
.getPrefix();
86 assert prefix
!= null;
87 return "".equals(prefix
) ? name
.getLocalPart() : prefix
+ ":" + name
.getLocalPart();
89 // ContentNamespace getNamespace();
93 public static UUID
namespaceUuid(String namespaceURI
) {
94 if (XMLConstants
.NULL_NS_URI
.equals(namespaceURI
))
96 Objects
.requireNonNull(namespaceURI
, "Namespace URI cannot be null");
97 synchronized (namespaceUuids
) {
98 UUID namespaceUuid
= namespaceUuids
.get(namespaceURI
);
99 if (namespaceUuid
== null) {
100 namespaceUuid
= nameUUIDv3(ContentName
.XMLNS_UUID
,
101 namespaceURI
.toString().getBytes(StandardCharsets
.UTF_8
));
102 namespaceUuids
.put(namespaceURI
, namespaceUuid
);
104 return namespaceUuid
;
108 public static UUID
nameUuid(String namespaceURI
, QName name
) {
109 return nameUuid(name
.getNamespaceURI(), name
.getLocalPart());
112 public static UUID
nameUuid(String namespaceURI
, String name
) {
113 Objects
.requireNonNull(namespaceURI
, "Namespace cannot be null");
114 Objects
.requireNonNull(name
, "Name cannot be null");
115 synchronized (nameUuids
) {
116 String key
= XMLConstants
.NULL_NS_URI
.equals(namespaceURI
) ? name
: "{" + namespaceURI
+ "}" + name
;
117 UUID nameUuid
= nameUuids
.get(key
);
118 if (nameUuid
== null) {
119 UUID namespaceUuid
= namespaceUuid(namespaceURI
);
120 nameUuid
= nameUUIDv3(namespaceUuid
, name
.getBytes(StandardCharsets
.UTF_8
));
121 namespaceUuids
.put(key
, nameUuid
);
128 * CANONICAL IMPLEMENTATION based on java.util.UUID.nameUUIDFromBytes(byte[])
130 static UUID
nameUUIDv3(UUID namespace
, byte[] name
) {
131 byte[] arr
= new byte[name
.length
+ 16];
132 ContentName
.copyUuidBytes(namespace
, arr
, 0);
133 System
.arraycopy(name
, 0, arr
, 16, name
.length
);
134 return UUID
.nameUUIDFromBytes(arr
);
137 static void copyUuidBytes(UUID uuid
, byte[] arr
, int offset
) {
138 long msb
= uuid
.getMostSignificantBits();
139 long lsb
= uuid
.getLeastSignificantBits();
140 assert arr
.length
>= 16 + offset
;
141 for (int i
= offset
; i
< 8 + offset
; i
++)
142 arr
[i
] = (byte) ((msb
>> ((7 - i
) * 8)) & 0xff);
143 for (int i
= 8 + offset
; i
< 16 + offset
; i
++)
144 arr
[i
] = (byte) ((lsb
>> ((15 - i
) * 8)) & 0xff);
151 public static boolean contains(QName
[] classes
, QName name
) {
152 for (QName clss
: classes
) {
153 if (clss
.equals(name
))