/* * 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.riot.out; import java.util.HashMap ; import java.util.Map ; import org.apache.jena.atlas.lib.InternalErrorException ; import org.apache.jena.graph.Node ; import org.apache.jena.riot.system.MapWithScope ; import org.apache.jena.riot.system.SyntaxLabels ; /** Map nodes to string (usually, blank nodes to labels). * See {@link SyntaxLabels#createNodeToLabel} for getting a default setup. */ public class NodeToLabel extends MapWithScope<Node, String, Node> { /** Allocation from a single scope; just the label matters. */ static public NodeToLabel createScopeByDocument() { return new NodeToLabel(new SingleScopePolicy(), new AllocatorIncLabel()) ; } // /** Allocation scoped by graph and label. */ // public static NodeToLabel createScopeByGraph() // { return new NodeToLabel(new GraphScopePolicy(), new AllocatorIncLabel()) ; } /** Allocation as per internal label, with an encoded safe label. */ public static NodeToLabel createBNodeByLabelEncoded() { return new NodeToLabel(new SingleScopePolicy(), new AllocatorInternalSafe()) ; } /** Allocation as per internal label */ public static NodeToLabel createBNodeByLabelAsGiven() { return new NodeToLabel(new SingleScopePolicy(), new AllocatorInternalRaw()) ; } /** Allocation as per internal label */ public static NodeToLabel createBNodeByIRI() { return new NodeToLabel(new SingleScopePolicy(), new AllocatorBNodeAsIRI()) ; } private static final NodeToLabel _internal = createBNodeByLabelEncoded() ; public static NodeToLabel labelByInternal() { return _internal ; } private NodeToLabel(ScopePolicy<Node, String, Node> scopePolicy, Allocator<Node, String, Node> allocator) { super(scopePolicy, allocator) ; } // ======== Scope Policies /** Single scope */ private static class SingleScopePolicy implements ScopePolicy<Node, String, Node> { private Map<Node, String> map = new HashMap<>() ; @Override public Map<Node, String> getScope(Node scope) { return map ; } @Override public void clear() { map.clear(); } } /** One scope for labels per graph */ private static class GraphScopePolicy implements ScopePolicy<Node, String, Node> { private Map<Node, String> dftMap = new HashMap<>() ; private Map<Node, Map<Node, String>> map = new HashMap<>() ; @Override public Map<Node, String> getScope(Node scope) { if ( scope == null ) return dftMap ; Map<Node, String> x = map.get(scope) ; if ( x == null ) { x = new HashMap<>() ; map.put(scope, x) ; } return x ; } @Override public void clear() { map.clear(); } } // ======== Allocators /** Allocator and some default policies. */ private abstract static class AllocatorBase implements Allocator<Node, String, Node> { // abstract to make you think about the policy! private long counter = 0 ; @Override public final String alloc(Node scope, Node node) { if ( node.isURI() ) return labelForURI(node) ; if ( node.isLiteral() ) return labelForLiteral(node) ; if ( node.isBlank() ) return labelForBlank(node) ; if ( node.isVariable() ) return labelForVar(node) ; throw new InternalErrorException("Node type not supported: "+node) ; } @Override public final String create() { return labelCreate() ; } // Just return a fresh label. protected String labelCreate() { return Long.toString(counter++) ; } protected String labelForURI(Node node) { return "<"+node.getURI()+">" ; } protected abstract String labelForBlank(Node node) ; protected String labelForLiteral(Node node) { return NodeFmtLib.str(node) ; } protected String labelForVar(Node node) { return "?"+node.getName() ; } @Override public void reset() {} } private static class AllocatorInternalRaw extends AllocatorBase { @Override protected String labelForBlank(Node node) { return "_:"+node.getBlankNodeLabel() ; } } private static class AllocatorInternalSafe extends AllocatorBase { @Override protected String labelForBlank(Node node) { // NodeFmtLib.safeBNodeLabel adds a "B" return "_:"+NodeFmtLib.encodeBNodeLabel(node.getBlankNodeLabel()) ; } } private static class AllocatorIncLabel extends AllocatorBase { private int X = 0 ; AllocatorIncLabel() {} @Override protected String labelForBlank(Node node) { return "_:b"+Integer.toString(X++) ; } } private static class AllocatorBNodeAsIRI extends AllocatorBase { @Override protected String labelForBlank(Node node) { // Needs to be safe? //String str = NodeFmtLib.safeBNodeLabel(node.getBlankNodeLabel()) ; String str = node.getBlankNodeLabel() ; return "<_:"+str+">" ; } } }