Github user rvesse commented on a diff in the pull request:
https://github.com/apache/jena/pull/431#discussion_r194338879
--- Diff:
jena-arq/src/main/java/org/apache/jena/sparql/graph/PrefixMappingBase.java ---
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.graph;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.StringJoiner;
+import java.util.function.BiConsumer;
+
+import org.apache.jena.ext.xerces.util.XMLChar;
+import org.apache.jena.shared.PrefixMapping;
+import org.apache.jena.util.SplitIRI;
+
+/**
+ * Framework for implementing {@link PrefixMapping}. It is stateless
(unlike
+ * {@code PrefixMappingImpl}) and implements the contract of {@link
PrefixMapping},
+ * providing the key algorithm and delegating storage to the subclasses.
+ * <p>
+ * Reverse mapping, looking up a URI to find a prefix is complex. There
may be several
+ * possibilities. Applications should not reliy on every implementat being
consistent,
+ * espeically when writing data when there has to be a choice on on prefix
to use to
+ * shorten a URI.
+ *
+ */
+public abstract class PrefixMappingBase implements PrefixMapping {
+ /* Reverse mappings.
+ * The strict contract of PrefixMapping requires a separate
reversemapping to be storoed and manipuated
+ * which in turn adds complexity to the storage implementations.
+ * However, applications removing prefixes is unusual so we end up
with a lot of complexity with little value.
+ *
+ * Beware of the details of removing a mapping when there is another
to the same URI.
+ * If we had:
+ *
+ * Add (pref1, U)
+ * Add (pref2, U)
+ *
+ * so that {@code U} reverse maps ({@link #getNsURIPrefix}) to {@code
pref2} (it was
+ * done second) then
+ *
+ * Remove (pref2)
+ *
+ * it causes {@code U} to reverse map to {@code pref1}.
+ *
+ * This feature is quite a burden on implementations and should be
regarded as "legacy" -
+ * an implementation may not support this complex effect.
+ *
+ * PrefixMappingMem does.
+ * Database backed ones typically don't.
+ */
+
+ protected PrefixMappingBase() {}
+
+ // The storage operations of an implementation.
+
+ /** Add prefix */
+ abstract protected void add(String prefix, String uri);
+
+ /** Remove prefix. */
+ abstract protected void remove(String prefix);
+
+ /** Clear all mappings */
+ abstract protected void clear();
+
+ abstract protected boolean isEmpty();
+
+ abstract protected int size();
+
+ /** Return the URI that the prefix maps to. */
+ abstract protected String prefixToUri(String prefix);
+
+ /** Return a prefix that maps to the URI.
+ * There may be several; the answer is any one of them.
+ */
+ abstract protected String uriToPrefix(String uri);
+
+ /** Return as a map. This map is only used within this class.
+ * It can be as efficient as possible.
+ * It will not be modifed.
+ * It wil not be retuned to a caller of {@code PrefixMappingBase}.
+ */
+ abstract protected Map<String, String> asMap();
+
+ /**
+ * Return as a map. The map return is not connected to the prefix
mapping implementation,
+ * does not reflect subsequent prefix mapping changes.
+ */
+ abstract protected Map<String, String> asMapCopy();
+
+ /** Apply the {@link BiConsumer} to each (prefix, uri) pair. */
+ abstract protected void apply(BiConsumer<String, String> action);
+
+ /**
+ * This part of the subclass API and may be overriden if an
implementation can do
+ * better This general implementation is based on asMap() which may be
a copy or may
+ * be a view of the storage directly.
+ */
+ protected Optional<Entry<String, String>> findMapping( String uri,
boolean partial ) {
+ return asMap().entrySet().stream().sequential().filter(e->{
+ String ss = e.getValue();
+ if (uri.startsWith( ss ) && (partial || ss.length() ==
uri.length()))
+ return true;
+ return false;
+ }).findFirst();
+ }
+
+ @Override
+ public PrefixMapping setNsPrefix(String prefix, String uri) {
+ checkLegal(prefix);
+ add(prefix, uri);
+ return this;
+ }
+
+ @Override
+ public PrefixMapping removeNsPrefix(String prefix) {
+ remove(prefix);
+ return this;
+ }
+
+ @Override
+ public PrefixMapping clearNsPrefixMap() {
+ clear();
+ return this;
+ }
+
+ /**
+ * Checks that a prefix is "legal" - it must be a valid XML NCName or
"". XML rules
+ * for RDF/XML output.
+ * <p>
+ * This is a recurring user question - why does {@code
Resource.getNamespace},
+ * {@code Resource.getLocalname} not abbreviate when it is legal
Turtle.
+ * <p>
+ * Answer - legacy for RDF/XML.
+ * <p>
+ * See also {@link #qnameFor}.
+ */
+ private void checkLegal(String prefix) {
--- End diff --
Could this be `public static` so this useful comment is included in Javadoc?
---