package org.drools.shapes; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.drools.rule.builder.dialect.asm.ClassGenerator; import org.drools.semantics.builder.DLFactory; import org.drools.semantics.builder.DLFactoryConfiguration; import org.drools.semantics.builder.model.Concept; import org.drools.semantics.builder.model.DRLModel; import org.drools.semantics.builder.model.JarModel; import org.drools.semantics.builder.model.ModelFactory; import org.drools.semantics.builder.model.OntoModel; import org.drools.semantics.builder.model.SemanticXSDModel; import org.drools.semantics.builder.model.SubConceptOf; import org.drools.semantics.builder.model.XSDModel; import org.drools.semantics.builder.model.compilers.ModelCompiler; import org.drools.semantics.builder.model.compilers.ModelCompilerFactory; import org.drools.semantics.builder.model.compilers.SemanticXSDModelCompiler; import org.drools.semantics.builder.model.compilers.XSDModelCompiler; import org.drools.semantics.utils.NameUtils; import org.drools.semantics.utils.NamespaceUtils; import org.jvnet.hyperjaxb3.maven2.Hyperjaxb3Mojo; import org.semanticweb.owlapi.model.IRI; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.util.InferredAxiomGenerator; import org.w3._2002._07.owl.Thing; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; public class OntoModelCompiler { public static final List<String> defaultOptions = Arrays.asList( "-extension", "-Xjaxbindex", "-Xannotate", "-Xinheritance", // "-XtoString", "-Xcopyable", "-Xmergeable", // "-Xvalue-constructor", "-Xfluent-api", "-Xkey-equality", "-Xsem-accessors", "-Xdefault-constructor", "-Xmetadata", "-XxcludeResolved", "-Xinject-code" ); public static final List<String> fullOptions = Arrays.asList( "-extension", "-Xjaxbindex", "-Xannotate", "-Xinheritance", "-XtoString", "-Xcopyable", "-Xmergeable", "-Xvalue-constructor", "-Xfluent-api", "-Xkey-equality", "-Xsem-accessors", "-Xdefault-constructor", "-Xmetadata", "-XxcludeResolved", "-Xinject-code" ); public static final List<String> minimalOptions = Arrays.asList( "-extension", "-Xjaxbindex", "-Xannotate", "-Xinheritance", // "-XtoString", // "-Xcopyable", // "-Xmergeable", // "-Xvalue-constructor", // "-Xfluent-api", "-Xkey-equality", "-Xsem-accessors", "-Xdefault-constructor", "-Xmetadata", "-XxcludeResolved", "-Xinject-code" ); public enum MOJO_VARIANTS { JPA2( "jpa2" ); private String label; MOJO_VARIANTS( String lab ) { label = lab; } public String getLabel() { return label; } } public enum COMPILATION_OPTIONS { DEFAULT( defaultOptions ), MINIMAL( minimalOptions ), FULL( fullOptions ); private List<String> options; COMPILATION_OPTIONS( List<String> opts ) { options = opts; } public List<String> getOptions() { return options; } } public enum AXIOM_INFERENCE { LITE( DLFactoryConfiguration.liteAxiomGenerators ), DEFAULT( DLFactoryConfiguration.defaultAxiomGenerators ), FULL( DLFactoryConfiguration.fullAxiomGenerators ), NONE( DLFactoryConfiguration.minimalAxiomGenerators ); private List<InferredAxiomGenerator<? extends OWLAxiom>> gens; AXIOM_INFERENCE( List<InferredAxiomGenerator<? extends OWLAxiom>> axiomGenerators ) { gens = axiomGenerators; } public List<InferredAxiomGenerator<? extends OWLAxiom>> getGenerators() { return gens; } } private File folder; private OntoModel model; public static final String METAINF = "META-INF"; public static final String DRL = "DRL"; public static final String JAVA = "java"; public static final String XJC = "xjc"; public static final String CLASSES = "classes"; public static String mavenTarget = "target"; public static String mavenSource = mavenTarget + File.separator + "generated-sources"; public static String metaInfDirName = mavenSource + File.separator + METAINF; public static String drlDirName = mavenSource + File.separator + DRL; public static String javaDirName = mavenSource + File.separator + JAVA; public static String xjcDirName = mavenSource + File.separator + XJC; public static String binDirName = mavenTarget + File.separator + CLASSES; private File metaInfDir; private File drlDir; private File javaDir; private File xjcDir; private File binDir; private List<File> preexistingSchemas = new ArrayList<File>(); private List<File> preesistingBindings = new ArrayList<File>(); public OntoModelCompiler( OntoModel model, File rootFolder ) { if ( ! rootFolder.exists() ) { rootFolder.mkdirs(); } this.folder = rootFolder; initDirectories(); this.model = model; lookupExistingSchemas(); } private void lookupExistingSchemas() { File folder = getMetaInfDir(); for ( File f : folder.listFiles( new FilenameFilter() { public boolean accept( File dir, String name ) { return name.endsWith( ".xsd" ) && ! "owlThing.xsd".equals( name ); } } ) ) { preexistingSchemas.add( f ); } for ( File f : folder.listFiles( new FilenameFilter() { public boolean accept( File dir, String name ) { return name.endsWith( ".xjb" ) && ! "global.xjb".equals( name ); } } ) ) { preesistingBindings.add( f ); } } private void initDirectories() { metaInfDir = new File( folder.getPath() + File.separator + metaInfDirName ); if ( ! metaInfDir.exists() ) { metaInfDir.mkdirs(); } drlDir = new File( folder.getPath() + File.separator + drlDirName ); if ( ! drlDir.exists() ) { drlDir.mkdirs(); } javaDir = new File( folder.getPath() + File.separator + javaDirName ); if ( ! javaDir.exists() ) { javaDir.mkdirs(); } xjcDir = new File( folder.getPath() + File.separator + xjcDirName ); if ( ! xjcDir.exists() ) { xjcDir.mkdirs(); } binDir = new File( folder.getPath() + File.separator + binDirName ); if ( ! binDir.exists() ) { binDir.mkdirs(); } } public void clearSources() { for ( File f : metaInfDir.listFiles() ) { f.delete(); } } public boolean existsResult() { return javaDir.listFiles().length > 0 || xjcDir.listFiles().length > 0 || drlDir.listFiles().length > 0; } public List<Diagnostic<? extends JavaFileObject>> compileOnTheFly(List<String> options, MOJO_VARIANTS variant) { streamJavaInterfaces( false ); streamXSDsWithBindings( true, null ); mojo( options, variant ); List<Diagnostic<? extends JavaFileObject>> diagnostics = doCompile(); return diagnostics; } public void fixResolvedClasses() { for ( Concept con : model.getConcepts() ) { if ( con.getResolvedAs() != Concept.Resolution.NONE ) { if ( con.getChosenProperties().size() > 0 ) { // This is very likely an extension/restriction of the original concept, so we need to redefine it String extPack = model.getDefaultPackage() + "." + con.getPackage(); model.removeConcept( con ); Concept original = con.clone(); original.getSubConcepts().clear(); original.getSubConcepts().add( con ); con.getSuperConcepts().clear(); con.addSuperConcept( original ); con.setChosenSuperConcept( original ); con.setPackage( extPack ); URI xuri = NameUtils.packageToNamespaceURI( extPack ); con.setNamespace( xuri.toASCIIString() ); con.setIri( IRI.create( NameUtils.separatingName( xuri.toASCIIString() ) + con.getName() ) ); model.addConcept( con ); model.addConcept( original ); } } } } public boolean streamDRLDeclares() throws MojoExecutionException { ModelCompiler compiler = ModelCompilerFactory.newModelCompiler( ModelFactory.CompileTarget.DRL ); boolean success; DRLModel drlModel = (DRLModel) compiler.compile( model ); try { FileOutputStream fos = new FileOutputStream( getDrlDir().getPath() + File.separator + model.getName() + "_declare.drl" ); success = drlModel.stream( fos ); fos.flush(); fos.close(); } catch ( IOException e ) { e.printStackTrace(); return false; } return success; } public boolean streamJavaInterfaces( boolean includeJar ) { ModelCompiler jcompiler = ModelCompilerFactory.newModelCompiler(ModelFactory.CompileTarget.JAR); JarModel jarModel = (JarModel) jcompiler.compile( model ); boolean success = jarModel.save( getJavaDir().getPath() ); if ( includeJar ) { try { FileOutputStream fos = new FileOutputStream( getBinDir().getPath() + File.separator + model.getName() + ".jar" ); byte[] content = jarModel.buildJar().toByteArray(); fos.write( content, 0, content.length ); fos.flush(); fos.close(); } catch ( IOException e ) { e.printStackTrace(); return false; } } return success; } public boolean streamXSDsWithBindings( boolean includePersistenceConfiguration ) { return streamXSDsWithBindings( includePersistenceConfiguration, null ); } public boolean streamXSDsWithBindings( boolean includePersistenceConfiguration, String persistenceTemplatePath ) { SemanticXSDModelCompiler xcompiler = (SemanticXSDModelCompiler) ModelCompilerFactory.newModelCompiler( ModelFactory.CompileTarget.XSDX ); SemanticXSDModel xmlModel = (SemanticXSDModel) xcompiler.compile( model ); xmlModel.streamAll( System.err ); boolean success = false; try { success = xmlModel.stream( getMetaInfDir() ); success = xmlModel.streamBindings( getMetaInfDir() ); if ( includePersistenceConfiguration ) { if ( persistenceTemplatePath != null ) { File persistenceTemplate = new File( persistenceTemplatePath ); if ( persistenceTemplate.exists() ) { InputStream is = new FileInputStream( persistenceTemplate ); byte[] data = new byte[ is.available() ]; is.read( data ); xmlModel.setPersistenceXml( new String( data ) ); is.close(); } } success = success && streamPersistenceConfigs( xcompiler, xmlModel ); } } catch ( Exception e ) { e.printStackTrace(); } return success; } protected boolean streamPersistenceConfigs( SemanticXSDModelCompiler xcompiler, SemanticXSDModel xmlModel ) throws IOException { boolean success; xcompiler.mergeNamespacedPackageInfo( xmlModel ); success = xmlModel.streamNamespacedPackageInfos( getXjcDir() ); File f2 = new File( getMetaInfDir().getPath() + File.separator + "empire.configuration.file" ); if ( f2.exists() ) { xcompiler.mergeEmpireConfig( f2, xmlModel ); } FileOutputStream fos2 = new FileOutputStream( f2 ); success = success && xmlModel.streamEmpireConfig( fos2 ); fos2.flush(); fos2.close(); File f3 = new File( getMetaInfDir().getPath() + File.separator + "empire.annotation.index" ); if ( f3.exists() ) { xcompiler.mergeIndex( f3, xmlModel ); } FileOutputStream fos3 = new FileOutputStream( f3 ); success = success && xmlModel.streamIndex( fos3 ); fos3.flush(); fos3.close(); File f4 = new File( getMetaInfDir().getPath() + File.separator + "persistence-template-hibernate.xml" ); // File f4 = new File( getXjcDir().getPath() + File.separator + "META-INF" + File.separator + "persistence.xml" ); // if ( f4.exists() ) { // xcompiler.mergePersistenceXml( f4, xmlModel ); // } FileOutputStream fos4 = new FileOutputStream( f4 ); success = success && xmlModel.streamPersistenceXml( fos4 ); fos4.flush(); fos4.close(); return success; } public boolean streamIndividualFactory() { ModelCompiler compiler = ModelCompilerFactory.newModelCompiler( ModelFactory.CompileTarget.XSDX ); SemanticXSDModel xsdModel; xsdModel = (SemanticXSDModel) compiler.compile( model ); boolean success = false; try { String classPath = getXjcDir().getPath() + File.separator + xsdModel.getDefaultPackage().replace(".", File.separator); File f = new File( classPath ); if ( ! f.exists() ) { f.mkdirs(); } FileOutputStream fos = new FileOutputStream( classPath + File.separator + "IndividualFactory.java" ); success = xsdModel.streamIndividualFactory( fos ); fos.flush(); fos.close(); } catch ( Exception e ) { e.printStackTrace(); return false; } return success; } public List<Diagnostic<? extends JavaFileObject>> doCompile() { List<File> list = new LinkedList<File>(); // Set<File> sourceFolders = new HashSet<File>(); // // // for ( String packageName : model.getAllPackageNames() ) { // sourceFolders.add( // new File( getXjcDir().getPath() + File.separator + packageName.replace(".", File.separator) ) // ); // sourceFolders.add( // new File( getJavaDir().getPath() + File.separator + packageName.replace(".", File.separator) ) // ); // } // // for ( File f : sourceFolders ) { // System.out.println( "************** COMPILER USING SRC FOLDERS AS " + f.getPath() ); // } // // sourceFolders.add( // new File( getXjcDir().getPath() + File.separator + "org.w3._2001.xmlschema".replace(".", File.separator) ) // ); // // // for ( File folder : sourceFolders ) { // if ( folder.exists() ) { // list.addAll( Arrays.asList( folder.listFiles( (FilenameFilter) new WildcardFileFilter( "*.java" ) ) ) ); // } // } explore( getJavaDir(), list ); explore( getXjcDir(), list ); // for ( File f : list ) { // System.out.println( "************** COMPILER USING SRC FILE AS " + f.getPath() ); // } JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); StandardJavaFileManager fileManager = jc.getStandardFileManager( diagnostics, null, null ); Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles( list ); List<String> jcOpts = Arrays.asList( "-d", getBinDir().getPath() ); JavaCompiler.CompilationTask task = jc.getTask( null, fileManager, diagnostics, jcOpts, null, compilationUnits ); task.call(); copyMetaInfResources(); return diagnostics.getDiagnostics(); } private void explore( File dir, List<File> files ) { for ( File f : dir.listFiles() ) { if ( f.getName().endsWith( ".java" ) ) { files.add( f ); } if ( f.isDirectory() ) { // System.out.println( "Looking for java in " + f.getPath() ); explore( f, files ); } } } private boolean copyMetaInfResources() { boolean success = true; success = success && copyMetaInfResources( getMetaInfDir() ); success = success && copyMetaInfResources( new File( getXjcDir() + File.separator + METAINF ) ); return success; } private boolean copyMetaInfResources( File src ) { File tgt = new File( getBinDir().getPath() + File.separator + METAINF ); if ( ! tgt.exists() ) { tgt.mkdir(); } for ( File f : src.listFiles( new FilenameFilter() { public boolean accept( File dir, String name ) { return ! name.contains( "template" ); } }) ) { try { copyFile( f, tgt ); } catch (IOException e) { e.printStackTrace(); return false; } } return true; } private void copyFile( File f, File tgtDir ) throws IOException { // System.out.println(" Trying to copy " + f.getName() + " into >>> " + tgtDir.getPath() ); FileInputStream fis = new FileInputStream( f ); byte[] buf = new byte[ fis.available() ]; fis.read( buf ); File tgt = new File( tgtDir.getPath() + File.separator + f.getName() ); FileOutputStream fos = new FileOutputStream( tgt ); fos.write( buf ); fis.close(); fos.flush(); fos.close(); } protected boolean streamMockPOM( File pom, String name ) { boolean success = false; try { FileOutputStream fos = new FileOutputStream( pom ); byte[] content = ( "" + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" + " <modelVersion>4.0.0</modelVersion>\n" + " <groupId>org.test</groupId>\n" + " <artifactId>" + name + "</artifactId>\n" + "</project>\n" + "" ).getBytes(); fos.write( content, 0, content.length ); fos.flush(); fos.close(); success = true; } catch ( IOException e ) { e.printStackTrace(); } return success; } public boolean mojo( List<String> args, MOJO_VARIANTS variant ) { boolean success = false; try { File pom = new File( folder.getPath() + File.separator + "pom.xml" ); if ( ! pom.exists() ) { success = streamMockPOM( pom, model.getName() ); } MavenProject mp = new MavenProject(); final Hyperjaxb3Mojo mojo = new Hyperjaxb3Mojo(); mojo.setVerbose( true ); mojo.setBindingDirectory( getMetaInfDir() ); mojo.setSchemaDirectory(getMetaInfDir()); int j = 0; String[] excludedSchemas = new String[ preexistingSchemas.size() ]; for ( File f : preexistingSchemas ) { excludedSchemas[ j++ ] = f.getName(); } mojo.setSchemaExcludes( excludedSchemas ); int k = 0; String[] excludedBindings = new String[ preesistingBindings.size() ]; for ( File f : preesistingBindings ) { excludedBindings[ k++ ] = f.getName(); } mojo.setBindingExcludes( excludedBindings ); mojo.setGenerateDirectory( getXjcDir() ); mojo.setExtension(true); mojo.variant = variant.getLabel(); File perx = new File( getBinDir().getPath() + File.separator + "META-INF" + File.separator + "persistence.xml" ); if ( perx.exists() ) { mojo.persistenceXml = perx; try { Document dox = parseXML( perx ); XPath xpath = XPathFactory.newInstance().newXPath(); XPathExpression expr = xpath.compile( "//persistence-unit/@name" ); mojo.persistenceUnitName = (String) expr.evaluate( dox, XPathConstants.STRING ); } catch ( Exception e ) { mojo.persistenceXml = new File( getMetaInfDir() + File.separator + "persistence-template-hibernate.xml" ); mojo.persistenceUnitName = model.getName(); } } else { mojo.persistenceXml = new File( getMetaInfDir() + File.separator + "persistence-template-hibernate.xml" ); mojo.persistenceUnitName = model.getName(); } mojo.generateEquals = false; mojo.generateHashCode = false; mojo.setProject( mp ); mojo.setArgs( args ); mojo.setForceRegenerate( true ); mojo.execute(); success = true; } catch (MojoExecutionException e) { e.printStackTrace(); } return success; } public File getMetaInfDir() { if ( ! metaInfDir.exists() ) { metaInfDir.mkdirs(); } return metaInfDir; } public File getDrlDir() { return drlDir; } public File getJavaDir() { if ( ! javaDir.exists() ) { javaDir.mkdirs(); } return javaDir; } public File getXjcDir() { if ( ! xjcDir.exists() ) { xjcDir.mkdirs(); } return xjcDir; } public File getBinDir() { if ( ! binDir.exists() ) { binDir.mkdirs(); } return binDir; } private Document parseXML( File f ) throws IOException, ParserConfigurationException, SAXException, TransformerException { InputSource xSource = new InputSource( new FileInputStream( f ) ); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbf.newDocumentBuilder(); return builder.parse( xSource ); } }