+ public static @NonNull NodeIdentifierWithPredicates of(final QName node) {
+ return new Regular(node, ImmutableMap.of());
+ }
+
+ public static @NonNull NodeIdentifierWithPredicates of(final QName node, final QName key, final Object value) {
+ return new Singleton(node, key, value);
+ }
+
+ public static @NonNull NodeIdentifierWithPredicates of(final QName node, final Entry<QName, Object> entry) {
+ return of(node, entry.getKey(), entry.getValue());
+ }
+
+ public static @NonNull NodeIdentifierWithPredicates of(final QName node, final Map<QName, Object> keyValues) {
+ return keyValues.size() == 1 ? of(keyValues, node)
+ // Retains ImmutableMap for empty maps. For larger sizes uses a shared key set.
+ : new Regular(node, ImmutableOffsetMap.unorderedCopyOf(keyValues));
+ }
+
+ public static @NonNull NodeIdentifierWithPredicates of(final QName node,
+ final ImmutableOffsetMap<QName, Object> keyValues) {
+ return keyValues.size() == 1 ? of(keyValues, node) : new Regular(node, keyValues);
+ }
+
+ private static @NonNull NodeIdentifierWithPredicates of(final Map<QName, Object> keyValues, final QName node) {
+ return of(node, keyValues.entrySet().iterator().next());
+ }
+
+ /**
+ * Return the set of predicates keys and values. Keys are guaranteeed to be unique.
+ *
+ * @return Predicate set.
+ */
+ public abstract @NonNull Set<Entry<QName, Object>> entrySet();
+
+ /**
+ * Return the predicate key in the iteration order of {@link #entrySet()}.
+ *
+ * @return Predicate values.
+ */
+ public abstract @NonNull Set<QName> keySet();
+
+ /**
+ * Determine whether a particular predicate key is present.
+ *
+ * @param key Predicate key
+ * @return True if the predicate is present, false otherwise
+ * @throws NullPointerException if {@code key} is null
+ */
+ public abstract boolean containsKey(QName key);
+
+ /**
+ * Return the predicate values in the iteration order of {@link #entrySet()}.
+ *
+ * @return Predicate values.
+ */
+ public abstract @NonNull Collection<Object> values();
+
+ @Beta
+ public final @Nullable Object getValue(final QName key) {
+ return keyValue(requireNonNull(key));
+ }
+
+ @Beta
+ public final <T> @Nullable T getValue(final QName key, final Class<T> valueClass) {
+ return valueClass.cast(getValue(key));
+ }
+
+ /**
+ * Return the number of predicates present.
+ *
+ * @return The number of predicates present.
+ */
+ public abstract int size();
+
+ /**
+ * A Map-like view of this identifier's predicates. The view is expected to be stable and effectively-immutable.
+ *
+ * @return Map of predicates.
+ */
+ @Beta
+ public abstract @NonNull Map<QName, Object> asMap();
+