+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+
+/**
+ * A {@link QName} which MUST have prefix and whose {@link #toString()} method
+ * returns the prefixed form (prefix:localPart).
+ */
+public class ContentName extends QName {
+ private static final long serialVersionUID = 5722920985400306100L;
+ public final static UUID NIL_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
+ /**
+ * The UUID v3 of http://www.w3.org/2000/xmlns/ within the standard DNS
+ * namespace, to be used as a base for the namespaces.
+ *
+ * @see https://www.w3.org/TR/xml-names/#ns-decl
+ */
+ // uuidgen --md5 --namespace @dns --name http://www.w3.org/2000/xmlns/
+ // NOTE : must be declared before default namespaces
+ public final static UUID XMLNS_UUID = UUID.fromString("4b352aad-ba1c-3139-b9d3-41e5816f6088");
+ // uuidgen --md5 --namespace 4b352aad-ba1c-3139-b9d3-41e5816f6088 --name ""
+ public final static UUID NULL_NS_UUID = UUID.fromString("f07726e3-99c8-3178-b758-a86ed41f300d");
+
+ private final static Map<String, UUID> namespaceUuids = Collections.synchronizedMap(new TreeMap<>());
+ private final static Map<String, UUID> nameUuids = Collections.synchronizedMap(new TreeMap<>());
+
+ static {
+ assert NULL_NS_UUID.equals(nameUUIDv3(XMLNS_UUID, XMLConstants.NULL_NS_URI.getBytes(UTF_8)));
+ }
+
+// private final UUID uuid;
+
+ public ContentName(String namespaceURI, String localPart, NamespaceContext nsContext) {
+ super(namespaceURI, localPart, checkPrefix(nsContext, namespaceURI));
+ }
+
+ private static String checkPrefix(NamespaceContext nsContext, String namespaceURI) {
+ Objects.requireNonNull(nsContext, "Namespace context cannot be null");
+ Objects.requireNonNull(namespaceURI, "Namespace URI cannot be null");
+ String prefix = nsContext.getNamespaceURI(namespaceURI);
+ if (prefix == null)
+ throw new IllegalStateException("No prefix found for " + namespaceURI + " from context " + nsContext);
+ return prefix;
+ }
+
+ ContentName(String namespaceURI, String localPart, String prefix) {
+ super(namespaceURI, localPart, prefix);
+ }
+
+ public ContentName(String localPart) {
+ super(XMLConstants.NULL_NS_URI, localPart, XMLConstants.DEFAULT_NS_PREFIX);
+ }
+
+ public ContentName(QName qName, NamespaceContext nsContext) {
+ this(qName.getNamespaceURI(), qName.getLocalPart(), nsContext);
+ }
+
+ public String toQNameString() {
+ return super.toString();
+ }
+
+ public String toPrefixedString() {
+ return toPrefixedString(this);
+ }
+
+ /*
+ * OBJECT METHOS
+ */
+
+ @Override
+ public String toString() {
+ return toPrefixedString();
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new ContentName(getNamespaceURI(), getLocalPart(), getPrefix());
+ }
+
+ public static String toPrefixedString(QName name) {
+ String prefix = name.getPrefix();
+ assert prefix != null;
+ return "".equals(prefix) ? name.getLocalPart() : prefix + ":" + name.getLocalPart();
+ }
+// ContentNamespace getNamespace();
+//
+// String getName();