/* * 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.system; import java.util.Map ; import org.apache.jena.atlas.lib.InternalErrorException ; /** Maps A's to B's, based on a scope S */ public class MapWithScope<A, B, S> { // ======== Interfaces public interface ScopePolicy<A, B, S> { Map<A, B> getScope(S scope) ; void clear() ; } /** Allocate a B, given some A. * Only called once per instance of B if the ScopePolicy map is non-null. */ public interface Allocator<A,B,S> { /** Allocate - return the same B for a given A. * "same" means .equals, not == */ public B alloc(S scope, A item) ; /** Create a fresh, unique (to within policy) B */ public B create() ; public void reset() ; } // ======== The Object // To be fully general, we should have an allocator per scope (and have an allocator factory). // But we don't need that complexity. private final ScopePolicy<A,B,S> scopePolicy ; private final Allocator<A,B,S> allocator ; protected MapWithScope(ScopePolicy<A,B,S> scopePolicy, Allocator<A,B,S> allocator) { this.scopePolicy = scopePolicy ; this.allocator = allocator ; } /** Get a B object for an A object in scope S object */ public B get(S scope, A item) { if ( item == null ) throw new InternalErrorException("null in MapWithScope.get(,null)") ; Map<A, B> map = scopePolicy.getScope(scope) ; if ( map == null ) // No map - no item->allocation tracking. return allocator.alloc(scope, item) ; B mappedItem = map.get(item) ; if ( mappedItem == null ) { mappedItem = allocator.alloc(scope, item) ; map.put(item, mappedItem) ; } return mappedItem ; } /** Create a label that is guaranteed to be fresh */ public B create() { return allocator.create() ; } /** Clear scope and allocation */ public void clear() { scopePolicy.clear() ; allocator.reset() ; } }