class QName {

    public static QName parseQName(final @NotNull NamespaceMapping mapping,
                                   final @NotNull Type type,
                                   final @NotNull String qName) {
        if (qName.startsWith("{") && qName.contains("}")) {
            final int lastBrace = qName.indexOf("}");
            final String uri = qName.substring(1, lastBrace);
            final String localName = qName.substring(lastBrace + 1);
            return new QName(type,
                    result1(mapping::getPrefix).apply(uri).toOptional().orElse(null),
                    localName, uri);
        } else if (qName.contains(":")) {
            final String[] parts = qName.split(":", 2);
            final String prefix = parts[0];
            final String localName = parts[1];
            return new QName(type, prefix, localName,
                    result1(mapping::getURI).apply(prefix).toOptional().orElse(null));
        }
        throw new UnqualifiedNameException(qName);
    }

    public  QName(final @NotNull Type type,
                 final @Nullable String prefix,
                 final @NotNull String localName,
                 final @Nullable String uri);

}