/*
* 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.enhanced;
import org.apache.jena.atlas.lib.Cache;
import org.apache.jena.atlas.lib.CacheFactory;
import org.apache.jena.graph.* ;
import org.apache.jena.rdf.model.RDFNode ;
/**
* {@code EnhGraph} wraps a {@link Graph plain graph}
* and contains {@link EnhNode enhanced nodes} that wrap the
* plain nodes of the plain graph. All the enhanced nodes in
* the enhanced graph share the same polymorphic personality.
*/
public class EnhGraph
{
// Instance variables
/** The graph that this enhanced graph is wrapping */
protected Graph graph;
/** Cache of enhanced nodes that have been created */
// 1000 seems to be a "about the right size" by experimentation.
protected Cache<Node, RDFNode> enhNodes = CacheFactory.createCache(1000);
/** The unique personality that is bound to this polymorphic instace */
private Personality<RDFNode> personality;
// Constructors
/**
* Construct an enhanced graph from the given underlying graph, and
* a factory for generating enhanced nodes.
*
* @param g The underlying plain graph, may be null to defer binding to a given
* graph until later.
* @param p The personality factory, that maps types to realisations
*/
public EnhGraph( Graph g, Personality<RDFNode> p ) {
super();
graph = g;
personality = p;
}
/**
* Answer the normal graph that this enhanced graph is wrapping.
* @return A graph
*/
public Graph asGraph() {
return graph;
}
/**
* Hashcode for an enhnaced graph is delegated to the underlyin graph.
* @return The hashcode as an int
*/
@Override final public int hashCode() {
return graph.hashCode();
}
/**
* An enhanced graph is equal to another graph g iff the underlying graphs
* are equal.
* This is deemed to be a complete and correct interpretation of enhanced
* graph equality, which is why this method has been marked final.
* <p> Note that this equality test does not look for correspondance between
* the structures in the two graphs. To test whether another graph has the
* same nodes and edges as this one, use {@link #isIsomorphicWith}.
* </p>
* @param o An object to test for equality with this node
* @return True if o is equal to this node.
* @see #isIsomorphicWith
*/
@Override final public boolean equals(Object o) {
return
this == o
|| o instanceof EnhGraph && graph.equals(((EnhGraph) o).asGraph());
}
/**
* Answer true if the given enhanced graph contains the same nodes and
* edges as this graph. The default implementation delegates this to the
* underlying graph objects.
*
* @param eg A graph to test
* @return True if eg is a graph with the same structure as this.
*/
final public boolean isIsomorphicWith(EnhGraph eg) {
return graph.isIsomorphicWith(eg.graph);
}
/**
* Answer an enhanced node that wraps the given node and conforms to the given
* interface type.
*
* @param n A node (assumed to be in this graph)
* @param interf A type denoting the enhanced facet desired
* @return An enhanced node
*/
public <X extends RDFNode> X getNodeAs( Node n, Class<X> interf ) {
// We use a cache to avoid reconstructing the same Node too many times.
EnhNode eh = (EnhNode) enhNodes.getIfPresent( n );
if ( eh == null ) {
// not in the cache, so build a new one
X constructed = personality.newInstance(interf, n, this) ;
enhNodes.put(n, constructed) ;
return constructed ;
}
else
return eh.viewAs( interf );
}
/**
* Set the cache controller object for this graph
* @param cc The cache controller
*/
public void setNodeCache(Cache<Node, RDFNode> cc) {
enhNodes = cc;
}
/**
* Answer the personality object bound to this polymorphic instance
*
* @return The personality object
*/
protected Personality<RDFNode> getPersonality() {
return personality;
}
}