package org.drools.semantics.builder.model;
import org.drools.core.util.StringUtils;
import org.drools.io.ResourceFactory;
import org.drools.semantics.builder.model.compilers.XSDModelCompiler;
import org.drools.semantics.utils.NameUtils;
import org.drools.semantics.utils.NamespaceUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLOntology;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.*;
public class XSDModelImpl extends ModelImpl implements XSDModel {
// private Document schema;
// map : namespace --> schema
private Map<Namespace, Document> schemas = new HashMap<Namespace, Document>();
// map : prefix --> namespace
protected Map<String,Namespace> prefixMap = new HashMap<String,Namespace>();
// map : namespace (String) --> prefix
protected Map<String,String> reversePrefixMap = new HashMap<String,String>();
// map : namespace --> schema file
protected Map<Namespace, String> schemaLocations = new HashMap<Namespace,String>();
XSDModelImpl() {
}
@Override
public void initFromBaseModel( OntoModel base ) {
super.initFromBaseModel(base);
setNamespace( "xsd", "http://www.w3.org/2001/XMLSchema" );
setNamespace( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
setNamespace( "tns", base.getDefaultNamespace() );
// setNamespace( "xjc", "http://java.sun.com/xml/ns/jaxb/xjc" );
schemas.put( getNamespace( "tns" ), initDocument( this.getDefaultNamespace() ) );
}
private Document initDocument( String tgtNamespace ) {
Document dox = new Document();
Element root = new Element( "schema", getNamespace( "xsd" ) );
root.setAttribute( "elementFormDefault", "qualified" );
root.setAttribute( "targetNamespace", NamespaceUtils.removeLastSeparator( tgtNamespace ) );
for ( Namespace ns : prefixMap.values() ) {
root.addNamespaceDeclaration( ns );
}
dox.addContent( root );
OWLOntology current = getOntology().getOWLOntologyManager().getOntology( IRI.create( tgtNamespace ) );
if ( current != null ) {
System.out.println( current.getOntologyID() + " imports " + current.getImports() );
Set<OWLOntology> imports = current.getImports();
for ( OWLOntology onto : imports ) {
System.out.println( " \t\t importing " + Namespace.getNamespace( onto.getOntologyID().getOntologyIRI().toURI().toString() ) );
String ns = onto.getOntologyID().getOntologyIRI().toURI().toString();
if ( getNamespace( ns ) != null ) {
addImport( dox, Namespace.getNamespace( ns ) );
}
}
}
if ( ! getNamespace( "tns" ).getURI().equals( NamespaceUtils.removeLastSeparator( tgtNamespace ) ) ) {
addImport( dox, getNamespace( "tns" ), true );
}
return dox;
}
public boolean streamAll( OutputStream os ) {
try {
// os.write( serialize( getXSDSchema() ).getBytes() );
os.write( getOWLSchema().getBytes() );
for ( Document dox : schemas.values() ) {
os.write( serialize( dox ).getBytes() );
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return false;
}
return true;
}
public boolean stream( File folder ) {
try {
for ( String ns : prefixMap.keySet() ) {
FileOutputStream os = null;
File target = null;
byte[] schemaBytes = null;
if ( "xsd".equals( ns ) || "xsi".equals( ns ) ) {
continue;
} else if ( "tns".equals( ns ) ) {
target = new File( folder.getPath() + File.separator + getDefaultPackage() + ".xsd" );
target = checkForSchemaOverride( target, prefixMap.get( ns ) );
os = new FileOutputStream( target );
schemaBytes = serialize( getXSDSchema( prefixMap.get( "tns" ) ) ).getBytes();
} else if ( "owl".equals( ns ) ) {
target = new File( folder.getPath() + File.separator + "owlThing.xsd" );
if ( ! target.exists() ) {
os = new FileOutputStream( target );
schemaBytes = getOWLSchema().getBytes();
}
} else {
String path = folder.getPath() + File.separator + NameUtils.namespaceURIToPackage( prefixMap.get( ns ).getURI() ) + ".xsd";
target = new File( path );
target = checkForSchemaOverride( target, prefixMap.get( ns ) );
if ( schemas.containsKey( prefixMap.get( ns ) ) ) {
os = new FileOutputStream( target );
schemaBytes = serialize( schemas.get( prefixMap.get( ns ) ) ).getBytes();
} else {
throw new IllegalStateException( "XSD Model stream : unrecognized namespace " + ns );
// os = new FileOutputStream( path );
// schemaBytes = serialize( initDocument( namespaces.get( ns ).getURI() ) ).getBytes();
}
}
if ( os != null ) {
schemaLocations.put( prefixMap.get( ns ), target.getPath() );
os.write( schemaBytes );
os.flush();
os.close();
}
}
// FileOutputStream fos = new FileOutputStream( folder.getPath() + File.separator + getDefaultPackage() + ".xsd" );
// fos.write( serialize( getXSDSchema() ).getBytes() );
// fos.flush();
// fos.close();
//
// FileOutputStream owl = new FileOutputStream( folder.getPath() + File.separator + "owlThing.xsd" );
// owl.write( getOWLSchema().getBytes() );
// owl.flush();
// owl.close();
//
//
// for ( Namespace ns : subSchemas.keySet() ) {
// String subFileName = folder.getPath() + File.separator + NameUtils.namespaceURIToPackage( ns.getURI() ) + ".xsd" ;
// FileOutputStream subFos = new FileOutputStream( subFileName );
// subFos.write( serialize( subSchemas.get( ns ) ).getBytes() );
// subFos.flush();
// subFos.close();
// }
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
private File checkForSchemaOverride( File tgt, Namespace namespace ) {
int j = 0;
File target = tgt;
String path = target.getPath();
String ns = namespace.getURI();
while ( target.exists() ) {
target = new File( path.replace( ".xsd", "_" + ( j++ ) + ".xsd" ) );
for ( Document dox : schemas.values() ) {
List<Element> imports = dox.getRootElement().getChildren( "import", NamespaceUtils.getNamespaceByPrefix( "xsd" ) );
for ( Element el : imports ) {
if ( el.getAttributeValue( "namespace" ).equals( ns ) ) {
el.setAttribute( "schemaLocation", target.getName() );
}
}
}
}
return target;
}
public Map<String, Namespace> getAssignedPrefixes() {
return prefixMap;
}
public Namespace getNamespace(String ns) {
return prefixMap.get( ns );
}
public Collection<Namespace> getNamespaces() {
return prefixMap.values();
}
public void setNamespace( String prefix, String namespace ) {
namespace = NamespaceUtils.removeLastSeparator( namespace );
Namespace ns = Namespace.getNamespace( prefix, namespace );
prefixMap.put( prefix, ns );
reversePrefixMap.put( namespace, prefix );
for ( Document dox : schemas.values() ) {
dox.getRootElement().addNamespaceDeclaration( ns );
}
}
public void addTrait( String name, Object trait ) {
XSDTypeDescr descr = (XSDTypeDescr) trait;
String prefix = reversePrefixMap.get( descr.getNamespace() );
Document schema = getXSDSchema( prefixMap.get( prefix ) );
schema.getRootElement().addContent( descr.getDeclaration() );
schema.getRootElement().addContent( descr.getDefinition() );
// now resolve required imports
for ( String depNs : descr.getDependencies() ) {
if ( ! reversePrefixMap.containsKey( depNs ) ) {
String px = mapNamespaceToPrefix( depNs );
createXSDSchema( Namespace.getNamespace( px, depNs ) );
}
addImport( schema, prefixMap.get( reversePrefixMap.get( depNs ) ) );
}
}
@Deprecated
public Document getXSDSchema() {
return schemas.get( getNamespace( "tns" ) );
}
// private Document getXSDSchema( String type ) {
// if ( type.indexOf( ":" ) >= 0 ) {
// return getXSDSchema();
// }
// if ( definesType( getXSDSchema(), type ) ) {
// return getXSDSchema();
// }
// for ( Document sub : subSchemas.values() ) {
// if ( definesType(sub, type) ) {
// return sub;
// }
// }
// return getXSDSchema();
// }
public Document getXSDSchema( Namespace altNamespace ) {
if ( schemas.containsKey( altNamespace ) ) {
return schemas.get( altNamespace );
} else {
Document dox = createXSDSchema( altNamespace );
return dox;
}
}
private Document createXSDSchema( Namespace altNamespace ) {
Document dox = initDocument( altNamespace.getURI() );
schemas.put( altNamespace, dox );
return dox;
}
public void addImport( Document dox, Namespace altNamespace ) {
addImport( dox, altNamespace, false );
}
public void addImport( Document dox, Namespace altNamespace, boolean forceTNS ) {
if ( ! forceTNS && altNamespace.equals( getNamespace( "tns" ) ) ) {
return;
}
List<Element> imports = dox.getRootElement().getChildren( "import", NamespaceUtils.getNamespaceByPrefix( "xsd" ) );
for ( Element e : imports ) {
if ( e.getAttributeValue( "namespace" ).equals( altNamespace.getURI() ) ) {
return;
}
}
Element imp = new Element( "import", getNamespace( "xsd" ) );
imp.setAttribute( "namespace", altNamespace.getURI() );
imp.setAttribute( "schemaLocation", getSchemaName( altNamespace ) );
dox.getRootElement().addContent( 0, imp );
}
private String getSchemaName( Namespace altNamespace ) {
if ( NamespaceUtils.getNamespaceByPrefix( "owl" ).getURI().equals( altNamespace.getURI() ) ) {
return "owlThing.xsd";
} else {
// String prefix = NamespaceUtils.compareNamespaces( altNamespace.getURI(), getDefaultNamespace() )
// ? ""
// : ( "_" + altNamespace.getPrefix() );
// return getName() + prefix + ".xsd";
return NameUtils.namespaceURIToPackage( altNamespace.getURI() ) + ".xsd";
}
}
public String mapNamespaceToPrefix( String namespace ) {
namespace = NamespaceUtils.removeLastSeparator( namespace );
String prefix;
if ( StringUtils.isEmpty( namespace ) ) {
prefix = "tns";
} else if ( NamespaceUtils.compareNamespaces( getDefaultNamespace(), namespace ) ) {
prefix = "tns";
} else if ( reversePrefixMap.containsKey( namespace ) ) {
prefix = reversePrefixMap.get( namespace );
} else if ( NamespaceUtils.isKnownSchema(namespace) ) {
prefix = NamespaceUtils.getPrefix( namespace );
reversePrefixMap.put( namespace, prefix );
setNamespace( prefix, namespace );
} else {
prefix = "ns" + ( reversePrefixMap.size() + 1 );
reversePrefixMap.put( namespace, prefix );
setNamespace( prefix, namespace );
}
return prefix;
}
public Object getTrait(String name) {
return null;
}
public Set<String> getTraitNames() {
Set<String> names = new HashSet<String>();
//TODO
return names;
}
@Override
protected String traitsToString() {
return serialize( getXSDSchema() );
}
protected String serialize( Document dox ) {
StringWriter out = new StringWriter();
XMLOutputter outputter = new XMLOutputter();
outputter.setFormat( Format.getPrettyFormat() );
try {
outputter.output( dox, out );
} catch (IOException e) {
e.printStackTrace();
}
return out.toString();
}
public String getOWLSchema() {
InputStream schemaIS = null;
try {
schemaIS = ResourceFactory.newClassPathResource("org/drools/semantics/builder/model/compilers/owlThing.xsd").getInputStream();
byte[] data = new byte[ schemaIS.available() ];
schemaIS.read( data );
return new String( data );
} catch ( Exception e ) {
e.printStackTrace();
return null;
}
}
public static class XSDTypeDescr {
private String name;
private String namespace;
private String effectiveName;
private String effectiveType;
private Element declaration;
private Element definition;
private Set<String> dependencies;
public XSDTypeDescr( String name, String namespace, String effectiveName, String effectiveType, Element declaration, Element definition, Set<String> dependencies ) {
this.name = name;
this.namespace = namespace;
this.effectiveName = effectiveName;
this.effectiveType = effectiveType;
this.declaration = declaration;
this.definition = definition;
this.dependencies = dependencies;
}
public String getName() {
return name;
}
public String getNamespace() {
return namespace;
}
public String getEffectiveName() {
return effectiveName;
}
public String getEffectiveType() {
return effectiveType;
}
public Element getDeclaration() {
return declaration;
}
public Element getDefinition() {
return definition;
}
public Set<String> getDependencies() {
return dependencies;
}
}
}