/* * 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 com.clarkparsia.empire.SupportsRdfId; import com.clarkparsia.empire.annotation.Namespaces; import com.clarkparsia.empire.annotation.RdfProperty; import com.clarkparsia.empire.annotation.RdfsClass; import org.drools.definition.type.PropertyReactive; import org.drools.factmodel.BuildUtils; import org.drools.factmodel.traits.Trait; import org.drools.semantics.utils.NameUtils; import org.drools.semantics.builder.model.*; import org.drools.semantics.utils.NamespaceUtils; import org.mvel2.asm.*; import thewebsemantic.Namespace; import thewebsemantic.RdfType; import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlID; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class JarInterfaceModelCompilerImpl extends JavaInterfaceModelCompilerImpl implements Opcodes, JarInterfaceModelCompiler { public void setModel(OntoModel model) { this.model = (CompiledOntoModel) ModelFactory.newModel( ModelFactory.CompileTarget.JAR, model ); } public void compile( Concept con, Object context, Map<String, Object> params ) { if ( "Thing".equals( con.getName() ) && NamespaceUtils.compareNamespaces("http://www.w3.org/2002/07/owl", con.getNamespace()) ) { return; } super.compile( con, context, params ); String name = con.getFullyQualifiedName(); ((JarModel) getModel()).addCompiledTrait( name, this.compile( name, params ) ); } private JarModelImpl.Holder compile( String trait, Map<String, Object> params ) { return compileInterface( trait, params ); } private JarModelImpl.Holder compileInterface( String trait, Map<String, Object> params ) { ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS ); FieldVisitor fv; MethodVisitor mv; AnnotationVisitor av0; Set<Concept> sup = ( (Set<Concept>) params.get( "superConcepts" ) ); String implInterface = (String) params.get( "implInterface" ); int N = sup.size() + 1 + ( implInterface != null ? 1 : 0 ); String[] superTypes = new String[ N ]; superTypes[0] = Type.getInternalName( SupportsRdfId.class ); int j = 1; if ( implInterface != null ) { superTypes[ j++ ] = implInterface.replace( ".", "/" ); } for ( Iterator<Concept> iter = sup.iterator(); iter.hasNext(); ) { superTypes[ j++ ] = iter.next().getFullyQualifiedName().replace( ".", "/" ); } Map<String, PropertyRelation> props = (Map<String, PropertyRelation>) params.get( "properties" ); cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, trait.replace( ".", "/" ), null, Type.getInternalName( Object.class ), superTypes); { av0 = cw.visitAnnotation( Type.getDescriptor( RdfsClass.class ), true); av0.visit( "value", "tns:" + params.get( "name" ) ); av0.visitEnd(); } { av0 = cw.visitAnnotation( Type.getDescriptor( Namespaces.class ), true); { //TODO : This does not work!! AnnotationVisitor av1 = av0.visitArray( "value" ); av1.visit( null, "tns" ); av1.visit( null, params.get( "namespace" ) ); av1.visitEnd(); } av0.visitEnd(); } { av0 = cw.visitAnnotation( Type.getDescriptor( Namespace.class ), true); av0.visit( "value", params.get( "namespace" ) ); } { av0 = cw.visitAnnotation( Type.getDescriptor( RdfType.class ), true); av0.visit( "value", "" + params.get( "name" ) + params.get( "namespace" ) ); } { av0 = cw.visitAnnotation( Type.getDescriptor( Trait.class ), true); } { av0 = cw.visitAnnotation( Type.getDescriptor( PropertyReactive.class ), true); } for ( String propKey : props.keySet() ) { PropertyRelation rel = props.get( propKey ); String propName = rel.getName(); propName = propName.substring( 0, 1 ).toUpperCase() + propName.substring( 1 ); String target = rel.getTarget().getFullyQualifiedName(); boolean isBoolean = target.equalsIgnoreCase( "xsd:boolean" ); if ( target.startsWith( "xsd:" ) ) { target = NameUtils.map( target, rel.getMaxCard() == null || rel.getMaxCard() != 1 ); } else { target = target.replace( ".", "/" ); } String propType = BuildUtils.getTypeDescriptor( target ); String genericGetType = null; String genericSetType = null; if ( rel.getMaxCard() == null || rel.getMaxCard() != 1 ) { genericGetType = "()Ljava/util/List<" + propType + ">;"; genericSetType = "(Ljava/util/List<" + propType + ">;)V"; propType = Type.getDescriptor( List.class ); isBoolean = false; } { mv = cw.visitMethod( ACC_PUBLIC + ACC_ABSTRACT, NameUtils.getter( rel.getName(), rel.getTarget().getName(), rel.getMaxCard() ), "()" + propType, genericGetType, null); if ( ! rel.isRestricted() && ! rel.isTransient() ) { av0 = mv.visitAnnotation( Type.getDescriptor( RdfProperty.class ), true ); av0.visit( "value", "tns:" + propName ); av0.visitEnd(); if ( rel.getTarget().isPrimitive() ) { av0 = mv.visitAnnotation( Type.getDescriptor( Basic.class ), true ); av0.visitEnd(); } else { if ( rel.getMaxCard() == null || rel.getMaxCard() > 1 ) { av0 = mv.visitAnnotation( Type.getDescriptor( OneToMany.class ), true ); } else { av0 = mv.visitAnnotation( Type.getDescriptor( ManyToOne.class ), true ); } { AnnotationVisitor av1 = av0.visitArray( "cascade" ); av1.visitEnum( null, Type.getDescriptor( CascadeType.class ), "ALL" ); av1.visitEnd(); } av0.visitEnd(); } } mv.visitEnd(); } { if ( ! rel.isReadOnly() ) { mv = cw.visitMethod( ACC_PUBLIC + ACC_ABSTRACT, NameUtils.setter( rel.getName() ), "(" + propType + ")V", genericSetType, null); mv.visitEnd(); } } { if ( ! rel.isRestricted() && ! rel.getTarget().isPrimitive() && ! rel.isTransient() ) { mv = cw.visitMethod( ACC_PUBLIC + ACC_ABSTRACT, "add" + NameUtils.compactUpperCase( rel.getName() ), "(" + Type.getDescriptor( Object.class ) + ")V", null, null ); { av0 = mv.visitAnnotation( Type.getDescriptor( Transient.class ), true ); av0.visitEnd(); } mv.visitEnd(); } } { if ( rel.isSimple() || ( ( rel.getMaxCard() == null || rel.getMaxCard() > 1 ) && ! rel.isTransient() ) ) { mv = cw.visitMethod( ACC_PUBLIC + ACC_ABSTRACT, "add" + NameUtils.compactUpperCase( rel.getName() ), "(L" + NameUtils.map( rel.getTarget().getFullyQualifiedName(), true ).replace( ".", "/" ) + ";)V", null, null ); { av0 = mv.visitAnnotation( Type.getDescriptor( Transient.class ), true ); av0.visitEnd(); } mv.visitEnd(); mv = cw.visitMethod( ACC_PUBLIC + ACC_ABSTRACT, "remove" + NameUtils.compactUpperCase( rel.getName() ), "(" + Type.getDescriptor( Object.class ) + ")V", null, null ); { av0 = mv.visitAnnotation( Type.getDescriptor( Transient.class ), true ); av0.visitEnd(); } mv.visitEnd(); } } } cw.visitEnd(); return new JarModelImpl.Holder( cw.toByteArray() ); } }