From 765ebf871d4ed0cc2b6f247ccc1f459e8f532491 Mon Sep 17 00:00:00 2001 From: sotty Date: Fri, 19 Jun 2015 18:37:26 -0500 Subject: [PATCH] [Shapes] Refactor metaclass generation to be decoupled from implementation class generation --- .../src/test/java/MetadataTest.java | 6 ++ .../lang/dl/DL_9_CompilationTest.java | 36 +++++++++ .../resources/ontologies/crossAttributes.owl | 64 ++++++++++++++++ .../compilers/MetaclassCompilerImpl.java | 74 +++++++++++++++---- .../inference/DelegateInferenceStrategy.java | 3 + .../model/java/TraitInterface.template | 4 +- .../templates/model/java/metaClass.template | 18 ++--- .../org.drools.semantics/utils/NameUtils.java | 11 ++- .../org/drools/semantics/NameUtilTest.java | 2 +- 9 files changed, 189 insertions(+), 29 deletions(-) create mode 100644 drools-shapes/drools-shapes-generator-plugin/src/test/resources/ontologies/crossAttributes.owl diff --git a/drools-shapes/drools-shapes-examples/tiny-example/src/test/java/MetadataTest.java b/drools-shapes/drools-shapes-examples/tiny-example/src/test/java/MetadataTest.java index a0478ef0..713ccfb1 100644 --- a/drools-shapes/drools-shapes-examples/tiny-example/src/test/java/MetadataTest.java +++ b/drools-shapes/drools-shapes-examples/tiny-example/src/test/java/MetadataTest.java @@ -11,6 +11,7 @@ import org.drools.core.util.StandaloneTraitFactory; import org.junit.Test; import org.test.MyKlass; +import org.test.MyKlass_; import org.test.MyTargetKlass; import org.w3._2002._07.owl.ThingImpl; @@ -32,6 +33,11 @@ public void testKlassAndMySubKlassWithImpl() { MySubKlass_ sk = new MySubKlass_( ski ); + MyKlass_ k = new MyKlass_( null ); + + + + assertEquals( 42, (int) sk.subProp.get( ski ) ); assertEquals( "hello", sk.prop.get( ski ) ); diff --git a/drools-shapes/drools-shapes-generator-plugin/src/test/java/org/drools/semantics/lang/dl/DL_9_CompilationTest.java b/drools-shapes/drools-shapes-generator-plugin/src/test/java/org/drools/semantics/lang/dl/DL_9_CompilationTest.java index e94f3f67..86249679 100644 --- a/drools-shapes/drools-shapes-generator-plugin/src/test/java/org/drools/semantics/lang/dl/DL_9_CompilationTest.java +++ b/drools-shapes/drools-shapes-generator-plugin/src/test/java/org/drools/semantics/lang/dl/DL_9_CompilationTest.java @@ -31,6 +31,7 @@ import org.drools.semantics.builder.DLFactoryConfiguration; import org.drools.semantics.builder.model.OntoModel; import org.drools.shapes.OntoModelCompiler; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -470,6 +471,41 @@ public void testMetadataMetaclassGenerationWithHierarchy() { } + @Test + public void testMetaclassWithCrossAttributes() { + + OntoModel results = factory.buildModel( "crossAttributes", + ResourceFactory.newClassPathResource( "ontologies/crossAttributes.owl" ), + DLFactoryConfiguration.newConfiguration( OntoModel.Mode.HIERARCHY ) ); + + assertTrue( results.isHierarchyConsistent() ); + + compiler = new OntoModelCompiler( results, folder.getRoot() ); + + // ****** Stream the java interfaces + boolean javaOut = compiler.streamJavaInterfaces( true ); + + assertTrue( javaOut ); + + // ****** Stream the XSDs, the JaxB customizations abd the persistence configuration + boolean metaOut = compiler.streamMetaclasses( false ); + assertTrue( metaOut ); + + showDirContent( folder ); + + List> diagnostics = compiler.doCompile(); + + boolean success = true; + for ( Diagnostic diag : diagnostics ) { + System.out.println( "ERROR : " + diag ); + if ( diag.getKind() == Diagnostic.Kind.ERROR ) { + success = false; + } + } + assertTrue( success ); + } + + @Test public void testRecognitionRuleGeneration() { diff --git a/drools-shapes/drools-shapes-generator-plugin/src/test/resources/ontologies/crossAttributes.owl b/drools-shapes/drools-shapes-generator-plugin/src/test/resources/ontologies/crossAttributes.owl new file mode 100644 index 00000000..f5967e0c --- /dev/null +++ b/drools-shapes/drools-shapes-generator-plugin/src/test/resources/ontologies/crossAttributes.owl @@ -0,0 +1,64 @@ +Prefix: dc: +Prefix: owl: +Prefix: rdf: +Prefix: xml: +Prefix: xsd: +Prefix: rdfs: +Prefix: test: + + + +Ontology: + + +AnnotationProperty: + + +Datatype: rdf:PlainLiteral + + +Datatype: xsd:string + + +ObjectProperty: test:myAttr + + Annotations: + "" + + Domain: + test:Klass1 or test:Klass2 + + Range: + test:Tgt1 or test:Tgt2 + + +Class: test:Klass1 + + SubClassOf: + test:myAttr only test:Tgt1 + + +Class: test:Klass2 + + SubClassOf: + ((test:myAttr some test:Tgt2) + and (test:myAttr min 0 test:Tgt2)) + and ((test:myAttr only test:Tgt2) + and (test:myAttr max 1 test:Tgt2)) + + +Class: test:Tgt2 + + +Class: test:Tgt1 + + +Individual: test:y + + +Individual: test:z + + +Individual: test:x + + diff --git a/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/compilers/MetaclassCompilerImpl.java b/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/compilers/MetaclassCompilerImpl.java index 5099fea5..c22cdf51 100644 --- a/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/compilers/MetaclassCompilerImpl.java +++ b/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/compilers/MetaclassCompilerImpl.java @@ -32,8 +32,10 @@ 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 MetaclassCompilerImpl extends ModelCompilerImpl implements MetaclassModelCompiler { @@ -57,36 +59,50 @@ public CompiledOntoModel compile( OntoModel model, boolean withMetaclasses ) { } @Override - public void compile( Concept con, Object target, Map params ) { + public void compile( Concept con, Object tgt, Map params ) { - if ( con.getIRI().toQuotedString().equals( Thing.IRI ) ) { + if ( con.getIRI().toQuotedString().equals( Thing.IRI ) || con.isAbstrakt() || con.isAnonymous() ) { return; } Map properties = new HashMap(); + Set localProperties = new HashSet(); propertyCache.put( con.getFullyQualifiedName(), properties ); for ( PropertyRelation prop : con.getAvailableProperties() ) { PropInfo p = new PropInfo(); + Concept target = findLocalRange( prop.getTarget() ); + p.propName = prop.getName(); - p.typeName = prop.getTarget().getFullyQualifiedName(); - p.simpleTypeName = prop.getTarget().getName(); + p.typeName = target.getFullyQualifiedName(); + p.simpleTypeName = target.getName(); p.propIri = prop.getIri(); - p.simple = prop.getTarget().isPrimitive(); - p.primitive = prop.getTarget().isPrimitive(); + p.simple = prop.getMaxCard() != null && prop.getMaxCard() == 1; + p.primitive = target.isPrimitive(); p.inherited = prop.isInherited(); - p.range = NameUtils.map( prop.getTarget().getFullyQualifiedName(), true ); + p.range = NameUtils.map( target.getFullyQualifiedName(), true ); p.javaRangeType = p.simple ? p.range : List.class.getName() + "<" + p.range + ">"; p.domain = prop.getDomain().getFullyQualifiedName(); String inverseName = prop.getInverse() != null ? prop.getInverse().getName() : null; - properties.put( p.propName, p ); + if ( prop.isRestricted() ) { + if ( ! prop.getTarget().isPrimitive() && ! prop.isTransient() && ! ( prop.isAttribute() && ! ( prop.getMaxCard() != null && prop.getMaxCard() == 1 ) ) ) { + properties.put( p.propName, p ); + } + } else { + properties.put( p.propName, p ); + } + + if ( isLocal( prop, con ) ) { + localProperties.add( p ); + } + if ( inverseName != null ) { @@ -125,26 +141,54 @@ public void compile( Concept con, Object target, Map params ) { } } + Concept parent = findConcreteParent( con.getChosenSuperConcept() ); HashMap map = new HashMap(); map.put( "klassName", con.getName() ); map.put( "typeName", con.getName() ); + map.put( "fullTypeName", con.getFullyQualifiedName() ); map.put( "package", con.getPackage() ); - map.put( "supertypeName", con.getChosenSuperConcept().getName() ); - map.put( "supertypePackage", con.getChosenSuperConcept().getPackage() ); + map.put( "supertypeName", parent.getName() ); + map.put( "supertypePackage", parent.getPackage() ); map.put( "typeIri", con.getIri() ); - map.put( "withImpl", useImplClasses ); + map.put( "withImpl", this.useImplClasses ); map.put( "properties", properties.values() ); + map.put( "localProperties", localProperties ); String metaClass = SemanticXSDModelCompilerImpl.getTemplatedCode( metaClassTempl, map ); - System.out.println( metaClass ); - model.addTrait( con.getFullyQualifiedName(), new AbstractJavaModelImpl.InterfaceHolder( metaClass, con.getPackage() ) ); } + private boolean isLocal( PropertyRelation prop, Concept con ) { + if ( con.getChosenProperties().containsValue( prop ) ) { + return true; + } + if ( prop.getDomain().isAnonymous() ) { + return true; + } + return con.getChosenSuperConcept().getAvailableProperties().contains( prop ); + } + + private Concept findLocalRange( Concept target ) { + if ( ! ( target.isAnonymous() || target.isAbstrakt() ) ) { + return target; + } else { + return findConcreteParent( target.getChosenSuperConcept() ); + } + } + + private Concept findConcreteParent( Concept chosenSuperConcept ) { + while ( chosenSuperConcept.isAbstrakt() || chosenSuperConcept.isAnonymous() ) { + if ( chosenSuperConcept == chosenSuperConcept.getChosenSuperConcept() ) { + return model.getConcept( Thing.IRI ); + } + chosenSuperConcept = chosenSuperConcept.getChosenSuperConcept(); + } + return chosenSuperConcept; + } public String buildFactory( String pack ) { @@ -157,7 +201,9 @@ public String buildFactory( String pack ) { if ( !pack.equals( con.getPackage() ) ) { continue; } - classNames.put( con.getName(), con.getFullyQualifiedName() ); + if ( ! con.isAbstrakt() ) { + classNames.put( con.getName(), con.getFullyQualifiedName() ); + } } return SemanticXSDModelCompilerImpl.getTemplatedCode( metaFactoryTempl, map ); } diff --git a/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/inference/DelegateInferenceStrategy.java b/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/inference/DelegateInferenceStrategy.java index 334bbf19..0e6aff95 100644 --- a/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/inference/DelegateInferenceStrategy.java +++ b/drools-shapes/drools-shapes-generator/src/main/java/org/drools/semantics/builder/model/inference/DelegateInferenceStrategy.java @@ -198,6 +198,8 @@ public DelegateInferenceStrategy() { register( "http://www.w3.org/2001/XMLSchema#unsignedInt", "xsd:unsignedInt" ); + register( "http://www.w3.org/2001/XMLSchema#base64Binary", "xsd:base64Binary" ); + register( "http://www.w3.org/2001/XMLSchema#anyURI", "xsd:anyURI" ); registerComplexConcept( "http://www.w3.org/2001/XMLSchema#List", "List" ); @@ -949,6 +951,7 @@ private Concept createConceptForComplexDatatype( OWLDataRange dataRange, OWLData } } this.conceptCache.put( iri.toQuotedString(), rangeCon ); + rangeCon.setAnonymous( true ); model.addConcept( rangeCon ); return rangeCon; } diff --git a/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/TraitInterface.template b/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/TraitInterface.template index 528448cb..a273ded5 100644 --- a/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/TraitInterface.template +++ b/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/TraitInterface.template @@ -32,10 +32,10 @@ import javax.persistence.Basic; // @{iri} -@RdfsClass( value="@{namespace}@{name}" ) +@RdfsClass( value="@{iri}" ) @Namespaces({ "tns", "@{namespace}" }) @thewebsemantic.Namespace( "@{namespace}" ) -@thewebsemantic.RdfType( "@{namespace}@{name}" ) +@thewebsemantic.RdfType( "@{iri}}" ) @org.drools.core.factmodel.traits.Trait @org.kie.api.definition.type.PropertyReactive public interface @{name} extends @if{ ! standalone } org.drools.semantics.Thing, @end{} org.drools.core.metadata.Metadatable @if{ implInterface != null} , @{ implInterface } @end{} diff --git a/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/metaClass.template b/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/metaClass.template index 4ba7f0a7..cbbe3912 100644 --- a/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/metaClass.template +++ b/drools-shapes/drools-shapes-generator/src/main/resources/org/drools/semantics/templates/model/java/metaClass.template @@ -10,7 +10,7 @@ public class @{ typeName }_ extends @if{ "Th metaClassInfo = @{ typeName }_Meta.getInstance(); } - @foreach{ prop : properties } @if{ ! prop.inherited } + @foreach{ prop : properties } @if{ localProperties.contains( prop ) } public static final org.drools.core.metadata.MetaProperty<@{ prop.domain },@{ prop.range },@{ prop.javaRangeType }> @{ prop.propName } = @{ typeName }_Meta.@{ prop.propName }; @end{}@end{ '\n' } @@ -44,7 +44,7 @@ public class @{ typeName }_ extends @if{ "Th public static @{ typeName }_Meta getInstance() { if ( instance == null ) { instance = new @{ typeName }_Meta( new org.drools.core.metadata.MetaProperty[] { - @foreach{ prop : properties } @if{ ! prop.inherited } @{ prop.propName }, @end{} @end{} + @foreach{ prop : properties } @if{ localProperties.contains( prop ) } @{ prop.propName }, @end{} @end{} } ); } return instance; @@ -52,7 +52,7 @@ public class @{ typeName }_ extends @if{ "Th @foreach{ prop : properties } - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } public static final org.drools.core.metadata.@if{ prop.simple }One@else{}Many@end{}ValuedMetaProperty <@{ prop.domain }, @{ prop.range }@if{ !prop.simple }, @{ prop.javaRangeType }@end{}> @{ prop.propName } = new @{ prop.concreteType }<@{prop.domain},@{ prop.range }> @@ -138,7 +138,7 @@ public class @{ typeName }_ extends @if{ "Th @foreach{ prop : properties } public @{ typeName }_NewInstance @{ prop.propName }( @{ prop.javaRangeType } value @if{ ! prop.simple }, org.drools.core.metadata.Lit mode @end{} ) { - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } getSetter().@{ prop.propName }( value @if{ ! prop.simple }, mode @end{} ); @else{} super.@{ prop.propName }( value @if{ ! prop.simple }, mode @end{} ); @@ -147,7 +147,7 @@ public class @{ typeName }_ extends @if{ "Th } @if{ ! prop.simple } public @{ typeName }_NewInstance @{ prop.propName }( @{ prop.range } value, org.drools.core.metadata.Lit mode ) { - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } getSetter().@{ prop.propName }( value, mode ); @else{} super.@{ prop.propName }( value, mode ); @@ -192,7 +192,7 @@ public class @{ typeName }_ extends @if{ "Th @foreach{ prop : properties } public @{typeName}_Modify @{ prop.propName }( @{ prop.javaRangeType } newVal @if{ ! prop.simple }, org.drools.core.metadata.Lit mode @end{} ) { - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } addTask( @{ prop.propName }, newVal, @if{ ! prop.simple } mode @else{} newVal != null ? org.drools.core.metadata.Lit.SET : org.drools.core.metadata.Lit.REMOVE @end{} ); @else{} super.@{ prop.propName }( newVal @if{ ! prop.simple }, mode @end{} ); @@ -201,7 +201,7 @@ public class @{ typeName }_ extends @if{ "Th } @if{ ! prop.simple } public @{typeName}_Modify @{ prop.propName }( @{ prop.range } newVal, org.drools.core.metadata.Lit mode ) { - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } addTask( @{ prop.propName }, java.util.Collections.singletonList( newVal ), mode ); @else{} super.@{ prop.propName }( newVal, mode ); @@ -239,7 +239,7 @@ public class @{ typeName }_ extends @if{ "Th @foreach{ prop : properties } public @{ typeName }_Don @{ prop.propName }( @{ prop.javaRangeType } value @if{ ! prop.simple }, org.drools.core.metadata.Lit mode @end{} ) { - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } getSetter().@{ prop.propName }( value @if{ ! prop.simple }, mode @end{} ); @else{} super.@{ prop.propName }( value @if{ ! prop.simple }, mode @end{} ); @@ -248,7 +248,7 @@ public class @{ typeName }_ extends @if{ "Th } @if{ ! prop.simple } public @{ typeName }_Don @{ prop.propName }( @{ prop.range } value, org.drools.core.metadata.Lit mode ) { - @if{ ! prop.inherited } + @if{ localProperties.contains( prop ) } getSetter().@{ prop.propName }( value, mode ); @else{} super.@{ prop.propName }( value, mode ); diff --git a/drools-shapes/drools-shapes-utilities/src/main/java/org.drools.semantics/utils/NameUtils.java b/drools-shapes/drools-shapes-utilities/src/main/java/org.drools.semantics/utils/NameUtils.java index 7a19c9dc..e27887cd 100644 --- a/drools-shapes/drools-shapes-utilities/src/main/java/org.drools.semantics/utils/NameUtils.java +++ b/drools-shapes/drools-shapes-utilities/src/main/java/org.drools.semantics/utils/NameUtils.java @@ -579,13 +579,14 @@ public static String capitalize( final String s ) { } private static String trail( String s ) { - //Pattern p = Pattern.compile( "_+$" ); - //return p.matcher( s.trim() ).group( 1 ); int start = s.length() - 1; + int count = 0; while ( start > 1 && s.charAt( start ) == '_' ) { start--; + count++; } - return s.substring( start + 1 ); + //return s.substring( start + 1 ); + return ""+count; } public static String compactUpperCase( final String name ) { @@ -712,6 +713,10 @@ public static String map( String dataType, boolean box ) { return box ? "java.lang.Long" : "long"; + } else if ( "xsd:base64Binary".equals( dataType ) ) { + + return box ? "java.lang.Byte[]" : "byte[]"; + } else { return dataType; } diff --git a/drools-shapes/drools-shapes-utilities/src/test/java/org/drools/semantics/NameUtilTest.java b/drools-shapes/drools-shapes-utilities/src/test/java/org/drools/semantics/NameUtilTest.java index ec5dcedd..32d39a01 100644 --- a/drools-shapes/drools-shapes-utilities/src/test/java/org/drools/semantics/NameUtilTest.java +++ b/drools-shapes/drools-shapes-utilities/src/test/java/org/drools/semantics/NameUtilTest.java @@ -12,7 +12,7 @@ public void testCompactWithTrailingUnderscores() { String s = "_foo_bar___"; String t = NameUtils.compactUpperCase( s ); System.out.println( t ); - assertEquals( "FooBar___", t ); + assertEquals( "FooBar3", t ); } }