/* * Copyright 2011 JBoss Inc * * Licensed 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.drools.semantics.builder.model.compilers; import org.drools.core.util.StringUtils; import org.drools.semantics.utils.NameUtils; import org.drools.semantics.builder.model.*; import org.drools.semantics.utils.NamespaceUtils; import org.jdom.Element; import org.jdom.Namespace; import org.w3._2002._07.owl.Thing; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class XSDModelCompilerImpl extends ModelCompilerImpl implements XSDModelCompiler { protected Map<String,Map<String,PropertyRelation>> propCache = new HashMap<String, Map<String, PropertyRelation>>(); private boolean transientPropertiesEnabled; private boolean useImplementation; public boolean isTransientPropertiesEnabled() { return transientPropertiesEnabled; } public void setTransientPropertiesEnabled(boolean transientPropertiesEnabled) { this.transientPropertiesEnabled = transientPropertiesEnabled; } public boolean isUseImplementation() { return useImplementation; } public void setUseImplementation(boolean useImplementation) { this.useImplementation = useImplementation; } public void setModel( OntoModel model ) { this.model = (CompiledOntoModel) ModelFactory.newModel( getCompileTarget(), model ); ((XSDModel) getModel()).setNamespace("tns", model.getDefaultNamespace()); } public void compile( Concept con, Object context, Map<String, Object> params ) { String name = con.getName().substring( con.getName().lastIndexOf( "." ) + 1 ); // if ( "Thing".equals( con.getName() ) && NamespaceUtils.compareNamespaces( "http://www.w3.org/2002/07/owl", con.getNamespace() ) ) { // return; // } if ( Thing.IRI.equals( con.getIri() ) ) { return; } String effectiveName = isUseImplementation() ? name + "Impl" : name; String effectiveType = ( (XSDModel) getModel() ).mapNamespaceToPrefix( con.getNamespace() ) + ":" + name; String namespace = NamespaceUtils.removeLastSeparator( con.getNamespace() ); Element element = new Element( "element", ((XSDModel) getModel()).getNamespace("xsd") ); element.setAttribute( "name", effectiveName ); element.setAttribute( "type", effectiveType ); Element el = buildType( con, params, isTransientPropertiesEnabled() ); Set<String> dependencies = new HashSet<String>(); dependencies.add( NamespaceUtils.removeLastSeparator( con.getChosenSuperConcept().getNamespace() ) ); for ( PropertyRelation prop : con.getEffectiveBaseProperties() ) { if ( ! prop.getTarget().isPrimitive() ) { dependencies.add( NamespaceUtils.removeLastSeparator( prop.getTarget().getNamespace() ) ); } } if ( dependencies.contains( namespace ) ) { dependencies.remove( namespace ); } XSDModelImpl.XSDTypeDescr descr = new XSDModelImpl.XSDTypeDescr( name, namespace, effectiveName, effectiveType, element, el, dependencies ); if ( model.getMode() != OntoModel.Mode.FLAT && model.getMode() != OntoModel.Mode.NONE && model.getMode() != OntoModel.Mode.DATABASE ) { getModel().addTrait( name, descr ); } else { if ( ! con.isAbstrakt() ) { getModel().addTrait( name, descr ); } } // // getModel().addTrait( name, el ); // if ( ((List) params.get( "keys" )).size() > 0 ) { // element.addContent( buildKeys( params ) ); // } } private Element buildKeys(Map<String, Object> params) { XSDModel xmodel = (XSDModel) getModel(); Element keys = new Element( "key", xmodel.getNamespace( "xsd" ) ); keys.setAttribute( "name", params.get( "name" ) + "Key" ); Element selector = new Element( "selector", xmodel.getNamespace( "xsd" ) ); selector.setAttribute( "xpath", "" + params.get( "name" ) ); keys.addContent( selector ); List<String> keyProps = (List<String>) params.get( "keys" ); for ( String k : keyProps ) { Element key = new Element( "field", xmodel.getNamespace( "xsd" ) ); key.setAttribute( "xpath", "@" + k ); keys.addContent( key ); } return keys; } private Element buildProperties( Concept con, Map<String, PropertyRelation> props, Element root, boolean includeTransient, boolean excludeInherited ) { Namespace xsdNs = ( (XSDModel) getModel() ).getNamespace( "xsd" ); String iri = con.getIri(); propCache.put( iri, props ); Element seq = isUseImplementation() ? new Element( "sequence", xsdNs ) : new Element( "sequence", xsdNs ); if ( isUseImplementation() ) { Element prop; prop = new Element( "element", xsdNs ); prop.setAttribute( "name", "dyEntryType" ); prop.setAttribute( "type", "xsd:string" ); prop.setAttribute( "minOccurs", "0" ); prop.setAttribute( "maxOccurs", "1" ); seq.addContent( prop ); } if ( isUseImplementation() ) { Element prop; prop = new Element( "element", xsdNs ); prop.setAttribute( "name", "dyReference" ); prop.setAttribute( "type", "xsd:boolean" ); prop.setAttribute( "minOccurs", "1" ); prop.setAttribute( "maxOccurs", "1" ); seq.addContent( prop ); } if ( isUseImplementation() ) { Element key = new Element( "element", xsdNs ); key.setAttribute( "name", "dyEntryId" ); key.setAttribute( "type", "xsd:string" ); key.setAttribute( "minOccurs", "1" ); key.setAttribute( "maxOccurs", "1" ); seq.addContent( key ); } root.addContent( seq ); for ( String propKey : props.keySet() ) { PropertyRelation rel = props.get( propKey ); Concept tgt = rel.getTarget(); if ( ( rel.isTransient() && ! includeTransient ) || ( rel.isInherited() && excludeInherited )) { continue; } Element prop = new Element( "element", xsdNs ); prop.setAttribute( "name", rel.getName() ); prop.setAttribute( "type", map( tgt ) ); Integer minCard = rel.getMinCard(); if (minCard == null) { minCard = 0; rel.setMinCard( 0 ); } Integer maxCard = rel.getMaxCard(); if (maxCard != null && maxCard == 0) { maxCard = null; rel.setMaxCard( null ); } prop.setAttribute( "minOccurs", rel.getMinCard().toString() ); prop.setAttribute( "maxOccurs", rel.getMaxCard() == null ? "unbounded" : rel.getMaxCard().toString() ); if ( ! tgt.isPrimitive() ) { String relTargetNamespace = NamespaceUtils.removeLastSeparator( tgt.getNamespace() ); ((XSDModelImpl) getModel()).addImport( ((XSDModelImpl) getModel()).getXSDSchema(), Namespace.getNamespace( relTargetNamespace ) ); } seq.addContent( prop ); } return seq; } private String map( Concept tgt ) { if ( tgt == null ) { return "xsd:anyType"; } String name = tgt.getName().substring( tgt.getName().lastIndexOf(".") + 1 ); String prefix = "tns"; if ( tgt.isPrimitive() ) { return tgt.getName(); } return ( (XSDModel) getModel() ).mapNamespaceToPrefix( tgt.getNamespace() ) + ":" + name ; } private Element buildType( Concept con, Map<String, Object> params, boolean includeTransient ) { Namespace xsdNs = ( (XSDModel) getModel() ).getNamespace( "xsd" ); String name = con.getName(); // name = isUseImplementation() ? name + "Impl" : name; Element type = new Element( "complexType",xsdNs ); type.setAttribute( "name", name ); Concept sup = con.getChosenSuperConcept(); Element complex = new Element( "complexContent", xsdNs ); Element ext = new Element( "extension", xsdNs ); ext.setAttribute( "base", ( (XSDModel) getModel() ).mapNamespaceToPrefix( sup.getNamespace() ) + ":" + sup.getName() ); if ( ! con.isResolved() ) { buildProperties( con, (Map<String, PropertyRelation>) params.get( "implProperties" ), ext, includeTransient, true ); } complex.setContent( ext ); type.setContent( complex ); return type; } public ModelFactory.CompileTarget getCompileTarget() { return ModelFactory.CompileTarget.XSD; } }