| ClassHierarchy.java |
/*****************************************************************************
* Source code information
* -----------------------
* Original author Ian Dickinson, HP Labs Bristol
* Author email Ian.Dickinson@hp.com
* Package Jena 2
* Web http://sourceforge.net/projects/jena/
* Created 27-Mar-2003
* Filename $RCSfile: ClassHierarchy.java.html,v $
* Revision $Revision: 1.2 $
* Release status $State: Exp $
*
* Last modified on $Date: 2003/09/02 14:48:50 $
* by $Author: ian_dickinson $
*
*****************************************************************************/
// Package
///////////////
// Imports
///////////////
import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.shared.PrefixMapping;
import java.io.PrintStream;
import java.util.*;
/**
* <p>
* Simple demonstration program to show how to list a hierarchy of classes. This
* is not a complete solution to the problem (sub-classes of restrictions, for example,
* are not shown). It is inteded only to be illustrative of the general approach.
* </p>
*
* @author Ian Dickinson, HP Labs
* (<a href="mailto:Ian.Dickinson@hp.com" >email</a>)
* @version CVS $Id: ClassHierarchy.java.html,v 1.2 2003/09/02 14:48:50 ian_dickinson Exp $
*/
public class ClassHierarchy {
// Constants
//////////////////////////////////
// Static variables
//////////////////////////////////
// Instance variables
//////////////////////////////////
protected OntModel m_model;
private Map m_anonIDs = new HashMap();
private int m_anonCount = 0;
// Constructors
//////////////////////////////////
// External signature methods
//////////////////////////////////
/** Show the sub-class hierarchy encoded by the given model */
public void showHierarchy( PrintStream out, OntModel m ) {
for (Iterator i = rootClasses( m ); i.hasNext(); ) {
showClass( out, (OntClass) i.next(), new ArrayList(), 0 );
}
}
// Internal implementation methods
//////////////////////////////////
/** Present a class, then recurse down to the sub-classes.
* Use occurs check to prevent getting stuck in a loop
*/
protected void showClass( PrintStream out, OntClass cls, List occurs, int depth ) {
renderClassDescription( out, cls, depth );
out.println();
// recurse to the next level down
if (cls.canAs( OntClass.class ) && !occurs.contains( cls )) {
for (Iterator i = cls.listSubClasses( true ); i.hasNext(); ) {
OntClass sub = (OntClass) i.next();
// we push this expression on the occurs list before we recurse
occurs.add( cls );
showClass( out, sub, occurs, depth + 1 );
occurs.remove( cls );
}
}
}
/**
* <p>Render a description of the given class to the given output stream.</p>
* @param out A print stream to write to
* @param c The class to render
*/
public void renderClassDescription( PrintStream out, OntClass c, int depth ) {
indent( out, depth );
if (c.isRestriction()) {
renderRestriction( out, (Restriction) c.as( Restriction.class ) );
}
else {
if (!c.isAnon()) {
out.print( "Class " );
renderURI( out, c.getModel(), c.getURI() );
out.print( ' ' );
}
else {
renderAnonymous( out, c, "class" );
}
}
}
/**
* <p>Handle the case of rendering a restriction.</p>
* @param out The print stream to write to
* @param r The restriction to render
*/
protected void renderRestriction( PrintStream out, Restriction r ) {
if (!r.isAnon()) {
out.print( "Restriction " );
renderURI( out, r.getModel(), r.getURI() );
}
else {
renderAnonymous( out, r, "restriction" );
}
out.print( " on property " );
renderURI( out, r.getModel(), r.getOnProperty().getURI() );
}
/** Render a URI */
protected void renderURI( PrintStream out, PrefixMapping prefixes, String uri ) {
out.print( prefixes.usePrefix( uri ) );
}
/** Render an anonymous class or restriction */
protected void renderAnonymous( PrintStream out, Resource anon, String name ) {
String anonID = (String) m_anonIDs.get( anon.getId() );
if (anonID == null) {
anonID = "a-" + m_anonCount++;
m_anonIDs.put( anon.getId(), anonID );
}
out.print( "Anonymous ");
out.print( name );
out.print( " with ID " );
out.print( anonID );
}
/** Generate the indentation */
protected void indent( PrintStream out, int depth ) {
for (int i = 0; i < depth; i++) {
out.print( " " );
}
}
/**
* Answer an iterator over the classes we will use as the roots of the depicted
* hierarchy. We use named classes that either have Thing as a direct super-class,
* or which have no declared super-classes. The first condition is helpful if
* using a reasoner, the second otherwise.
* @param m A model
* @return An iterator over the named class hierarchy roots in m
*/
protected Iterator rootClasses( OntModel m ) {
List roots = new ArrayList();
for (Iterator i = m.listClasses(); i.hasNext(); ) {
OntClass c = (OntClass) i.next();
// too confusing to list all the restrictions as root classes
if (c.isAnon()) {
continue;
}
if (c.hasSuperClass( m.getProfile().THING(), true ) ) {
// this class is directly descended from Thing
roots.add( c );
}
else if (c.getCardinality( m.getProfile().SUB_CLASS_OF() ) == 0 ) {
// this class has no super-classes (can occur if we're not using the reasoner)
roots.add( c );
}
}
return roots.iterator();
}
//==============================================================================
// Inner class definitions
//==============================================================================
}