#!/usr/bin/perl

# Requires cgi-lib.pl from http://cgi-lib.berkeley.edu/

##############
# Owl Converter Modifications by David Rager
# (c) 2003 BBN Techonologies, LLC (A Verizon Company)
# Released June 2003
#
# Anyone is welcome to use, modify, and distribute this code as
# long as this message is left in the script
#
# The converter was changed to have the following added functionality:
#
# New defaultBase input parameter allows user to set the xml:base of the document.
# Changes all old DAML namespaces to OWL (with the exception of the default namespace).
# Changes XML Schema namespace to http://www.w3.org/2001/XMLSchema.
# Checks for namespace changes in DOCTYPE entity definitions.
# Converter no longer discards lines before the RDF tag.
# Removes the import of OWL.
# Replaces the DAML URI with the OWL URI in the body of the document (in rdf:resource, rdf:about, etc).
# Replaces the complete list of duplicate DAML tags with originals from RDF(S)
#    (comment, domain, Property, List, first, Datatype, etc).
# Changes URIs that end in .daml to .owl
# Prints the number of lines in the converted file, or a warning if the file was empty.
#
# The converter has the following limitations:
#
# Does not change XMLSchema Datatype references to the xml:datatype attribute form.
# Lazy about tag/namespace renaming, so could change some literal values that are similar to changed items.
# Will not work properly if there are no newlines in the input file.
# May not work correctly if there is more than one DAML namespace defined.
# Assumes owl was not already defined as a namespace
#
##############

##############
# Owl Converter - converts DAML+OIL ontologies to OWL
# (c) 2002, Jennifer Golbeck
# v 1.1, released 19 Mar 03
#
# Anyone is welcome to use, modify, and distribute this code as
# long as this message is left in the script
##############



#### The following segment of code uses CGI Lib ###

use CGI qw(:standard);

$file = &param('inFile');
$outFile = &param('outFile');
$defaultNs = &param('defaultNs');
$defaultXMLBase = &param('defaultBase');

if ($file eq "") {
	print "Error: No inFile specified\n";	
	exit;
}
if ($outFile eq "") {
	print "Error: No outFile specified\n";	
	exit;
}


##### End code for CGI Lib Users #####

### Users without CGI Lib - uncomment these 3 lines ###
#$file = "damlFile.daml";
#$outFile = "owlFile.owl";
#$defaultNs = "newDefaultNamespace";
#$defaultXMLBase = "newXMLBase";
############################



print "Converting $file to OWL in file $outFile\n";

#0 means we're not there yet, 1 means we're in the RDF tag, 2 means we're done with it
$inheader=0;

#do we need to ignore their defaultNs
$ignore=0;

#have we added their defaultNs
$addedDefaultNs=0;

#have we added their xml:base
$addedBase=0;
#abbreviation for the daml namespace
$damlns="";

#abbreviation for the xsd namespace
$xsdns="";
$xdsent="";

open (OWL, ">$outFile");
open (FILE, $file);

# Count the number of lines
$linecount=0;

# Does this work if the input file does not contain any newlines?

while (<FILE>) {
    $linecount++;
    #    print "$inheader $xsdns $xsdent $_";
    if ($inheader<2) {
	if (($_ =~ /<(\s*)(\S*)*RDF/) && ($inheader==0 || $inheader==.5))  {
	    $inheader=1;
	}
	if (($_ =~ /<(\s*)!DOCTYPE/) && $inheader==0)  {
	    $inheader=.5;
	}

	# in DOCTYPE Tag
	if ($inheader==.5) {
	    # Check for DAML (http://www.daml.org/2001/03/daml+oil) ENTITY definition, change URI to OWL
	    if ($_ =~ /ENTITY(\s*)(\S*)(\s*)(\"|\')http:\/\/www\.daml\.org\/2001\/03\/daml\+oil(\#|\"|\')/) {
		$damlent = $2;
		$_ =~ s/http:\/\/www\.daml\.org\/2001\/03\/daml\+oil/http:\/\/www\.w3\.org\/2002\/07\/owl/;
	    }

	    # Check for DAML (http://www.daml.org/2000/12/daml+oil) ENTITY definition, change URI to OWL 
	    if ($_ =~ /ENTITY(\s*)(\S*)(\s*)(\"|\')http:\/\/www\.daml\.org\/2000\/12\/daml\+oil(\#|\"|\')/) {
		$damlent = $2;
		$_ =~ s/http:\/\/www\.daml\.org\/2000\/12\/daml\+oil/http:\/\/www\.w3\.org\/2002\/07\/owl/;
	    }

	    # Check for DAML (http://www.daml.org/2000/10/daml-ont#) ENTITY definition, change URI to OWL 
	    if ($_ =~ /ENTITY(\s*)(\S*)(\s*)(\"|\')http:\/\/www\.daml\.org\/2000\/10\/daml\-ont(\#|\"|\')/) {
		$damlent = $2;
		$_ =~ s/http:\/\/www\.daml\.org\/2000\/10\/daml\-ont/http:\/\/www\.w3\.org\/2002\/07\/owl/;
	    }

	    # Check for XML Schema ENTITY, change to current URI
	    if ($_ =~ /ENTITY(\s*)(\S*)(\s*)(\"|\')http:\/\/www\.w3\.org\/2000\/10\/XMLSchema(\#|\"|\')/) {
		$xsdent = $2;
		$_ =~ s/http:\/\/www\.w3\.org\/2000\/10\/XMLSchema/http:\/\/www\.w3\.org\/2001\/XMLSchema/;
	    }

	    # End of DOCTYPE tag.
	    if ($_ =~ /\]>/ ) {
		$inheader==0;
	    }	

	    # Replace .daml# with .owl#
	    $_ =~ s/\.daml(\#|\"|\')/\.owl$1/g;
	}

	# in RDF tag (namespace declarations)
	if ($inheader==1) {

	    # Check for DAML namespace using the DAML entity substitution
	    if ($_ =~ /xmlns:(\S*)(\s*)=(\s*)(\"|\')&$damlent;/) {
		$damlns=$1;
		$_ =~ s/xmlns:$damlns/xmlns:owl/;
	    }
	    # Check for the DAML namespace (http://www.daml.org/2001/03/daml+oil), and substitute in OWL URI
	    if ($_ =~ /xmlns:(\S*)(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2001\/03\/daml\+oil(\#|\"|\')/ ) {
		$damlns= $1;	
		$quote = $4;
		$owlns = " xmlns:owl=$4http:\/\/www\.w3\.org\/2002\/07\/owl";
		$_ =~ s/xmlns:(\S*)(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2001\/03\/daml\+oil/$owlns/;
	    }
	    # Check for the DAML namespace (http://www.daml.org/2000/12/daml+oil), and substitute in OWL URI
	    if ($_ =~ /xmlns:(\S*)(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2000\/12\/daml\+oil(\#|\"|\')/ ) {
		$damlns= $1;	
		$quote = $4;
		$owlns = " xmlns:owl=$4http:\/\/www\.w3\.org\/2002\/07\/owl";
		$_ =~ s/xmlns:(\S*)(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2000\/12\/daml\+oil/$owlns/;
	    }
	    # Check for the DAML namespace (http://www.daml.org/2000/10/daml-ont#), and substitute in OWL URI
	    if ($_ =~ /xmlns:(\S*)(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2000\/10\/daml\-ont(\#|\"|\')/ ) {
		$damlns= $1;	
		$quote = $4;
		$owlns = " xmlns:owl=$4http:\/\/www\.w3\.org\/2002\/07\/owl";
		$_ =~ s/xmlns:(\S*)(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2000\/10\/daml\-ont/$owlns/;
	    }
	    # Check for the DAML namespace as the default namespace, and substitute in OWL URI
	    if ($_ =~ /xmlns(\s*)=(\s*)(\"|\')http:\/\/www\.daml\.org\/2001\/03\/daml\+oil(\#|\"|\')/) {
		$damlns = "";		
		$quote = $3;
		$owlns = " xmlns=$3http:\/\/www\.w3\.org\/2002\/07\/owl";
		$_ =~ s/xmlns=(\"|\')http:\/\/www\.daml\.org\/2001\/03\/daml\+oil/$owlns/;
		
		# Set flag that indicates we found the default namespace
		if ($defaultNs ne "" || $defaultNs =~ /^\s*$/) {
		    $ignore=1;
		    $addedDefaultNs=1;
		}
	    }

	    #get rid of any spaces in the daml ns
	    $damlns =~ s/ //ig;

	    #replace defaultNs if we have one
	    if (!($defaultNs =~ /^\s*$/) && $defaultNs ne "" && ignore != 1 && $addedDefaultNs !=1) {
		if ($_ =~ /xmlns(\s*)=(\s*)\"(\S+)\"/) {
		    $_ =~ s/$3/$defaultNs/;
		    $addedDefaultNs=1;
		}				
	    }

	    # Check for the xsd namespace using an entity substitution
	    if ($_ =~ /xmlns:(\S*)(\s*)=(\s*)(\"|\')&$xsdent;/) {
		$xsdns=$1;
	    }

	    # Check for the xsd namespace, and update URI
	    if ($_ =~ /xmlns:(\S*)(\s)=(\s*)(\"|\')http:\/\/www\.w3\.org\/2000\/10\/XMLSchema(\#|\"|\')/) {
		$xsdns=$1;
		$_ =~ s/http:\/\/www\.w3\.org\/2000\/10\/XMLSchema/http:\/\/www\.w3\.org\/2001\/XMLSchema/;
	    }

	    # If there exists an xml:base attribute
	    if ($_ =~ /xml:base(\s*)=(\s*)\"(\S+)\"/) {
		# $3 is the xml:base value
		# print OWL "found xml:base $3\n";
		# if a defaultBase was specified...
		if ($defaultXMLBase ne "") {
		    # replace specified base with the given base
		    $_ =~ s/$3/$defaultXMLBase/;
		    $addedBase=1;
		}
	    }

	    # Add an xml:base if specified and have not done so already
	    if ($_ =~ />/) {
		$inheader=2;
		if ($addedBase == 0 && $defaultXMLBase ne "") {
		    $_ =~ s/>/ xml:base=\"$defaultXMLBase\">/;
		    $addedBase=1;
		}
	    }

	    # Closing of RDF start tag, add a default namespace if needed.
	    if ($_ =~ />/) {
		$inheader=2;
		#if we haven't had to replace a default ns so far, and none was given, add it
		if ($addedDefaultNs == 0 && $defaultNs ne "") {
		    $_ =~ s/>/ xmlns=\"$defaultNs\">/;
		}		
	    }

	    # Replace .daml# with .owl#
	    $_ =~ s/\.daml(\#|\"|\')/\.owl$1/g;

	}

	# Moved this outside the if statment, so anything before the header gets
	# saved (such as the XML header).
	# Removed extra newline that was printed 
	print  OWL "$_";
	break;

    } else {
	#done with the header. set up the damlns in case it was the default ns
	# Assumes that the owl namespace did not exist before.
	if ($damlns ne "") {
	    $_ =~ s/$damlns:/owl:/g;
	}
	
	# Remove import of owl
	$_ =~ s/(\s*)<(\s*)owl:imports(\s+)rdf:resource=\"http:\/\/www\.daml\.org\/2001\/03\/daml\+oil\"(\s*)\/>(\s*)//g;
	$_ =~ s/(\s*)<(\s*)owl:imports(\s+)rdf:resource=\"&$damlent;\"(\s*)\/>(\s*)//g;
	
	# replace occurences of the DAML+OIL URI that appear in the body of the document.
	# this does not check to see if it is just appearing as text in some literal, but
	# that's true for most of this section
	$_ =~ s/http:\/\/www\.daml\.org\/2001\/03\/daml\+oil#/http:\/\/www\.w3\.org\/2002\/07\/owl#/g;
	
	# Changed the xmlschema uri
	$_ =~ s/http:\/\/www.w3.org\/2000\/10\/XMLSchema/http:\/\/www.w3.org\/2001\/XMLSchema/g;
	
	# Removed duplicate names from DAML
	# the namespace was converted to OWL above
	$_ =~ s/owl:comment/rdfs:comment/g;
	$_ =~ s/owl:domain/rdfs:domain/g;
	$_ =~ s/owl:label/rdfs:label/g;
	$_ =~ s/owl:isDefinedBy/rdfs:isDefinedBy/g;
	$_ =~ s/owl:Literal/rdfs:Literal/g;
	$_ =~ s/owl:Property/rdf:Property/g;
	$_ =~ s/owl:range/rdfs:range/g;
	$_ =~ s/owl:seeAlso/rdfs:seeAlso/g;
	$_ =~ s/owl:subClassOf/rdfs:subClassOf/g;
	$_ =~ s/owl:subPropertyOf/rdfs:subPropertyOf/g;
	$_ =~ s/owl:type/rdf:type/g;
	$_ =~ s/owl:value/rdf:value/g;
	
	$_ =~ s/owl:Datatype(\s|\>)/rdfs:Datatype$1/g;
	$_ =~ s/owl:collection/Collection/g;
	$_ =~ s/daml:collection/Collection/g;
	$_ =~ s/owl:List/rdf:List/g;
	$_ =~ s/owl:first/rdf:first/g;
	$_ =~ s/owl:rest/rdf:rest/g;
	$_ =~ s/http:\/\/www\.w3\.org\/2002\/07\/owl#nil/http:\/\/www\.w3\.org\/1999\/02\/22-rdf-syntax-ns#nil/g;
	$_ =~ s/&$damlent;#nil/http:\/\/www\.w3\.org\/1999\/02\/22-rdf-syntax-ns#nil/g;
	
	# Removed from DAML
	$_ =~ s/owl:(c|minC|maxC)ardinalityQ/daml:$1ardinality_REMOVED_FROM_LANGUAGE/g;
	$_ =~ s/owl:hasClassQ/daml:hasClass_REMOVED_FROM_LANGUAGE/g;
	
	# Renamed items from DAML -> OWL
	$_ =~ s/owl:differentIndividualFrom/owl:differentFrom/g;
	$_ =~ s/owl:equivalentTo/owl:sameAs/g;
	$_ =~ s/owl:sameClassAs/owl:equivalentClass/g;
	$_ =~ s/owl:samePropertyAs/owl:equivalentProperty/g;
	$_ =~ s/owl:hasClass/someValuesFrom/g;
	$_ =~ s/owl:sameClassAs/owl:equivalentClass/g;
	$_ =~ s/owl:samePropertyAs/owl:equivalentProperty/g;
	$_ =~ s/owl:toClass/owl:allValuesFrom/g;
	$_ =~ s/owl:UnambiguousProperty/owl:InverseFunctionalProperty/g;
	$_ =~ s/owl:UniqueProperty/owl:FunctionalProperty/g;
	$_ =~ s/owl:equvalentTo/owl:sameAs/g;
	
	# change the way datatypes are used
	# this isn't working, because the tags span across multiple lines.
	#	$xsd = "http:\/\/www\.w3\.org\/2001\/XMLSchema";
	#	if ($_ =~ /<(\s*)(\S*)(\s*)>(/s*)<(/s*)($xsdns:|$xsd#)(/S*)(/s*)rdf:value(/s*)=(/s*)\"*?\"(/s*)\/>(/s*)<\/(/s*)$2(/s*)>/)
	#	    $_ =~ s/<(/s*)*?(/s*)>(/s*)<(/s*)($xsdns:|$xsd#)(/S*)(/s*)rdf:value(/s*)=(/s*)\"*?\"(/s*)\/>(/s*)<\/(/s*)$2(/s*)>/<$2 rdf:datatype=\"$xsd#$6\">$10<\/$2>/;
	#	    print "$_\n";
	#					  }
	
	# Replace .daml# with .owl#
	$_ =~ s/\.daml(\#|\"|\')/\.owl$1/g;

	# Removed extra newline that was printed
	print  OWL "$_";
    }
}
if ($linecount == 0) {
    print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
    print "WARNING: Input file contains no data!\n";
    print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n";
} else {
    print "converted $linecount lines\n\n";
}

