org.drools.semantics.lang.dl.DL_9_CompilationTest.java Source code

Java tutorial

Introduction

Here is the source code for org.drools.semantics.lang.dl.DL_9_CompilationTest.java

Source

/*
 * 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.lang.dl;

import com.clarkparsia.empire.Empire;
import com.clarkparsia.empire.EmpireOptions;
import com.clarkparsia.empire.config.ConfigKeys;
import com.clarkparsia.empire.config.EmpireConfiguration;
import com.clarkparsia.empire.sesame.OpenRdfEmpireModule;
import com.clarkparsia.empire.sesame.RepositoryDataSourceFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import org.apache.commons.lang.StringUtils;
import org.drools.io.ResourceFactory;
import org.drools.semantics.UIdAble;
import org.drools.semantics.builder.DLFactory;
import org.drools.semantics.builder.DLFactoryBuilder;
import org.drools.semantics.builder.DLFactoryConfiguration;
import org.drools.semantics.builder.model.OntoModel;
import org.drools.shapes.OntoModelCompiler;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import thewebsemantic.binding.Jenabean;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.spi.PersistenceProvider;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
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.IOException;
import java.io.PrintStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertFalse;

/**
 * This is a sample class to launch a rule.
 */
@SuppressWarnings("restriction")
public class DL_9_CompilationTest {

    protected DLFactory factory = DLFactoryBuilder.newDLFactoryInstance();

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    protected OntoModelCompiler compiler;

    @Test
    public void testDiamondOptimizedHierarchyCompilation() {

        OntoModel results = factory.buildModel("diamond",
                ResourceFactory.newClassPathResource("ontologies/diamondProp2.manchester.owl"),
                DLFactoryConfiguration.newConfiguration(OntoModel.Mode.OPTIMIZED));

        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 xsdOut = compiler.streamXSDsWithBindings(true);

        assertTrue(xsdOut);
        File f = new File(compiler.getMetaInfDir() + File.separator + results.getDefaultPackage() + ".xsd");
        try {
            Document dox = parseXML(f, true);

            NodeList types = dox.getElementsByTagName("xsd:complexType");
            assertEquals(10, types.getLength());

            NodeList elements = dox.getElementsByTagName("xsd:element");
            assertEquals(12 + 14, elements.getLength());
        } catch (Exception e) {
            fail(e.getMessage());
        }

        showDirContent(folder);

        File b = new File(compiler.getMetaInfDir() + File.separator + results.getDefaultPackage() + ".xjb");
        try {
            Document dox = parseXML(b, false);

            NodeList types = dox.getElementsByTagName("bindings");
            assertEquals(28, types.getLength());
        } catch (Exception e) {
            fail(e.getMessage());
        }

        showDirContent(folder);

        // ****** Generate sources
        boolean mojo = compiler.mojo(
                Arrays.asList("-extension", "-Xjaxbindex", "-Xannotate", "-Xinheritance", "-XtoString",
                        "-Xcopyable", "-Xmergeable", "-Xvalue-constructor", "-Xfluent-api", "-Xkey-equality",
                        "-Xsem-accessors", "-Xdefault-constructor", "-Xmetadata", "-Xinject-code"),
                OntoModelCompiler.MOJO_VARIANTS.JPA2);

        assertTrue(mojo);

        File klass = new File(compiler.getXjcDir().getPath() + File.separator
                + results.getDefaultPackage().replace(".", File.separator) + File.separator + "BottomImpl.java");
        printSourceFile(klass, System.out);

        showDirContent(folder);

        // ****** Do compile sources
        List<Diagnostic<? extends JavaFileObject>> 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);

        showDirContent(folder);

        try {
            parseXML(new File(compiler.getBinDir() + "/META-INF/" + "persistence.xml"), true);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            ClassLoader urlKL = new URLClassLoader(new URL[] { compiler.getBinDir().toURI().toURL() },
                    Thread.currentThread().getContextClassLoader());

            testPersistenceWithInstance(urlKL, "org.jboss.drools.semantics.diamond2.Bottom", results.getName());

        } catch (Exception e) {
            e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
            fail(e.getMessage());
        }

    }

    @Test
    public void testIncrementalCompilation() {
        try {

            OntoModel diamond = factory.buildModel("diamondX",
                    ResourceFactory.newClassPathResource("ontologies/diamondProp.manchester.owl"),
                    DLFactoryConfiguration.newConfiguration(OntoModel.Mode.OPTIMIZED));

            compiler = new OntoModelCompiler(diamond, folder.getRoot());

            List<Diagnostic<? extends JavaFileObject>> diag1 = compiler
                    .compileOnTheFly(OntoModelCompiler.minimalOptions, OntoModelCompiler.MOJO_VARIANTS.JPA2);

            for (Diagnostic<?> dx : diag1) {
                System.out.println(dx);
                assertFalse(dx.getKind() == Diagnostic.Kind.ERROR);
            }

            showDirContent(folder);

            ClassLoader urlKL = new URLClassLoader(new URL[] { compiler.getBinDir().toURI().toURL() },
                    Thread.currentThread().getContextClassLoader());

            OntoModel results = factory.buildModel("diamondInc",
                    ResourceFactory.newClassPathResource("ontologies/dependency.test.owl"),
                    DLFactoryConfiguration.newConfiguration(OntoModel.Mode.OPTIMIZED), urlKL);

            System.out.println(results);

            Class bot = Class.forName("org.jboss.drools.semantics.diamond.BottomImpl", true, urlKL);
            Class botIF = Class.forName("org.jboss.drools.semantics.diamond.Bottom", true, urlKL);
            Assert.assertNotNull(bot);
            Assert.assertNotNull(botIF);
            Object botInst = bot.newInstance();
            Assert.assertNotNull(botInst);

            OntoModelCompiler compiler2 = new OntoModelCompiler(results, folder.getRoot());

            compiler2.fixResolvedClasses();

            compiler2.streamJavaInterfaces(false);
            compiler2.streamXSDsWithBindings(true);

            compiler2.mojo(OntoModelCompiler.defaultOptions, OntoModelCompiler.MOJO_VARIANTS.JPA2);

            showDirContent(folder);

            File unImplBoundLeft = new File(compiler2.getXjcDir() + File.separator
                    + "org.jboss.drools.semantics.diamond".replace(".", File.separator) + File.separator
                    + "Left.java");
            assertFalse(unImplBoundLeft.exists());
            File implBoundLeft = new File(compiler2.getXjcDir() + File.separator
                    + "org.jboss.drools.semantics.diamond".replace(".", File.separator) + File.separator
                    + "LeftImpl.java");
            assertTrue(implBoundLeft.exists());

            File leftInterface = new File(compiler2.getJavaDir() + File.separator
                    + "org.jboss.drools.semantics.diamond".replace(".", File.separator) + File.separator
                    + "Left.java");

            assertTrue(leftInterface.exists());

            List<Diagnostic<? extends JavaFileObject>> diagnostics = compiler2.doCompile();

            for (Diagnostic<?> dx : diagnostics) {
                System.out.println(dx);
                assertFalse(dx.getKind() == Diagnostic.Kind.ERROR);
            }

            showDirContent(folder);

            Document dox = parseXML(new File(compiler2.getBinDir().getPath() + "/META-INF/persistence.xml"), false);
            XPath xpath = XPathFactory.newInstance().newXPath();
            XPathExpression expr = xpath.compile("//persistence-unit/@name");
            assertEquals("diamondX", (String) expr.evaluate(dox, XPathConstants.STRING));

            File YInterface = new File(compiler2.getJavaDir() + File.separator
                    + "org.jboss.drools.semantics.diamond".replace(".", File.separator) + File.separator
                    + "X.java");
            assertTrue(YInterface.exists());

            Class colf = Class.forName("some.dependency.test.ChildOfLeftImpl", true, urlKL);
            Assert.assertNotNull(colf);
            Object colfInst = colf.newInstance();

            List<String> hierarchy = getHierarchy(colf);
            assertTrue(hierarchy.contains("some.dependency.test.ChildOfLeftImpl"));
            assertTrue(hierarchy.contains("some.dependency.test.org.jboss.drools.semantics.diamond.LeftImpl"));
            assertTrue(hierarchy.contains("org.jboss.drools.semantics.diamond.LeftImpl"));
            assertTrue(hierarchy.contains("org.jboss.drools.semantics.diamond.C0Impl"));
            assertTrue(hierarchy.contains("org.jboss.drools.semantics.diamond.TopImpl"));
            assertTrue(hierarchy.contains("org.w3._2002._07.owl.ThingImpl"));

            Set<String> itfHierarchy = getIFHierarchy(colf);

            System.err.println(itfHierarchy.containsAll(
                    Arrays.asList("org.jboss.drools.semantics.diamond.C1", "org.jboss.drools.semantics.diamond.C0",
                            "some.dependency.test.org.jboss.drools.semantics.diamond.Left",
                            "some.dependency.test.ChildOfLeft", "org.jboss.drools.semantics.diamond.Left",
                            "org.jboss.drools.semantics.diamond.Top", "com.clarkparsia.empire.EmpireGenerated",
                            "org.w3._2002._07.owl.Thing", "java.io.Serializable", "org.drools.semantics.Thing",
                            "com.clarkparsia.empire.SupportsRdfId")));

            Method getter1 = colf.getMethod("getAnotherLeftProp");
            assertNotNull(getter1);
            Method getter2 = colf.getMethod("getImportantProp");
            assertNotNull(getter2);

            for (Method m : colf.getMethods()) {
                if (m.getName().equals("addImportantProp")) {
                    m.getName();
                }
            }

            Method adder = colf.getMethod("addImportantProp", botIF);
            assertNotNull(adder);
            adder.invoke(colfInst, botInst);
            List l = (List) getter2.invoke(colfInst);
            assertEquals(1, l.size());

            File off = new File(compiler2.getXjcDir() + File.separator
                    + "org.jboss.drools.semantics.diamond".replace(".", File.separator) + File.separator
                    + "Left_Off.java");
            assertFalse(off.exists());

            testPersistenceWithInstance(urlKL, "org.jboss.drools.semantics.diamond.Bottom", diamond.getName());
            System.out.println(" Done");

        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }

    }

    private Set<String> getIFHierarchy(Class x) {
        Set<String> l = new HashSet<String>();
        extractInterfaces(x, l);
        return l;
    }

    private void extractInterfaces(Class x, Set<String> l) {
        for (Class itf : x.getInterfaces()) {
            l.add(itf.getName());
            extractInterfaces(itf, l);
        }
    }

    private List<String> getHierarchy(Class x) {
        List<String> l = new LinkedList<String>();
        Class k = x;
        while (!k.equals(Object.class)) {
            l.add(k.getName());
            k = k.getSuperclass();
        }
        return l;
    }

    private void testPersistenceWithInstance(ClassLoader urlKL, String cName, String pUnit) {
        Object bot = null;

        try {
            bot = createTestFact(urlKL, cName);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
        if (bot != null) {
            checkJaxbRefresh(bot, urlKL);

            checkEmpireRefresh(bot, urlKL);

            checkSQLRefresh(bot, urlKL, pUnit);

            checkJenaBeansRefresh(bot, urlKL);
        }
    }

    private void checkJenaBeansRefresh(Object bot, ClassLoader urlk) {
        ClassLoader oldKL = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(urlk);

            OntModel m = ModelFactory.createOntologyModel();
            Jenabean.instance().bind(m);
            Jenabean.instance().writer().saveDeep(bot);

            m.write(System.err);

            Object x = Jenabean.instance().reader().load(bot.getClass(), ((UIdAble) bot).getDyEntryId());

            try {
                checkEquality(bot, x);
            } catch (Exception e) {
                e.printStackTrace();
                Assert.fail(e.getMessage());
            }

        } finally {
            Thread.currentThread().setContextClassLoader(oldKL);
        }

    }

    private void checkSQLRefresh(Object obj, ClassLoader urlk, String punit) {
        ClassLoader oldKL = Thread.currentThread().getContextClassLoader();
        EntityManagerFactory emf = null;
        EntityManager em = null;
        try {
            Thread.currentThread().setContextClassLoader(urlk);

            HashMap props = new HashMap();
            props.put("hibernate.hbm2ddl.auto", "create-drop");
            emf = Persistence.createEntityManagerFactory(punit, props);

            em = emf.createEntityManager();

            checkJPARefresh(obj, ((UIdAble) obj).getDyEntryId(), em);

        } finally {
            Thread.currentThread().setContextClassLoader(oldKL);
            if (em != null && em.isOpen()) {
                em.clear();
                em.close();
            }
            if (emf != null && emf.isOpen()) {
                emf.close();
            }
        }

    }

    private void checkEmpireRefresh(Object obj, ClassLoader urlk) {
        File config = new File(compiler.getBinDir() + File.separator + compiler.METAINF + File.separator
                + "empire.configuration.file");
        File annox = new File(compiler.getBinDir() + File.separator + compiler.METAINF + File.separator
                + "empire.annotation.index");

        ClassLoader oldKL = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(urlk);

            checkJPARefresh(obj, ((UIdAble) obj).getRdfId(),
                    initEmpireEM(config, annox, obj.getClass().getPackage().getName()));
        } finally {
            Thread.currentThread().setContextClassLoader(oldKL);
        }

    }

    private void checkJPARefresh(Object obj, Object key, EntityManager em) {

        persist(obj, em);

        Object obj2 = refreshOnJPA(obj, key, em);

        System.out.println(obj2);

        try {
            checkEquality(obj, obj2);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }

    }

    private void checkEquality(Object obj, Object obj2)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object c0 = obj2.getClass().getMethod("getC0Prop").invoke(obj2);
        assertTrue(c0 instanceof List && ((List) c0).size() == 2);

        Object cX = obj2.getClass().getMethod("getObjPropX").invoke(obj2);
        assertNotNull(cX);
        System.out.println(cX);
        assertTrue(cX.getClass().getName().endsWith("XImpl"));

        Object c2 = obj2.getClass().getMethod("getC2Prop").invoke(obj2);
        assertTrue(c2 instanceof List && ((List) c2).size() == 1 && ((List) c2).get(0) instanceof String);
    }

    private EntityManager initEmpireEM(File config, File annox, String pack) {
        System.setProperty("empire.configuration.file", config.getPath());
        EmpireConfiguration ecfg = new EmpireConfiguration();
        ecfg.getGlobalConfig().put(ConfigKeys.ANNOTATION_INDEX, annox.getPath());
        Empire.init(ecfg, new OpenRdfEmpireModule());
        EmpireOptions.STRICT_MODE = false;

        PersistenceProvider aProvider = Empire.get().persistenceProvider();

        EntityManagerFactory emf = aProvider.createEntityManagerFactory(pack, getTestEMConfigMap());
        EntityManager em = emf.createEntityManager();
        return em;
    }

    private static Map<String, String> getTestEMConfigMap() {
        Map<String, String> aMap = new HashMap<String, String>();

        aMap.put(ConfigKeys.FACTORY, RepositoryDataSourceFactory.class.getName());
        aMap.put(RepositoryDataSourceFactory.REPO, "test-repo");
        aMap.put(RepositoryDataSourceFactory.FILES, "");
        aMap.put(RepositoryDataSourceFactory.QUERY_LANG, RepositoryDataSourceFactory.LANG_SERQL);

        return aMap;
    }

    private void persist(Object o, EntityManager em) {
        em.getTransaction().begin();
        em.persist(o);
        em.getTransaction().commit();
        em.clear();
    }

    private Object refreshOnJPA(Object o, Object key, EntityManager em) {
        Object ret = null;
        em.getTransaction().begin();
        ret = em.find(o.getClass(), key);
        em.getTransaction().commit();
        return ret;
    }

    private Object createTestFact(ClassLoader urlKL, String cName) throws Exception {
        Class bottom = Class.forName(cName, true, urlKL);
        Class bottomImpl = Class.forName(cName + "Impl", true, urlKL);

        Object bot = bottomImpl.newInstance();
        assertTrue(bottom.isAssignableFrom(bot.getClass()));

        assertNotNull(bottomImpl.getMethod("getObjPropX"));
        assertNotNull(bottomImpl.getMethod("getObjPropXs"));

        Object ret = bottomImpl.getMethod("getObjPropXs").invoke(bot);
        assertNotNull(ret);
        assertTrue(ret instanceof List);
        assertEquals(1, ((List) ret).size());

        bottom.getMethod("addC1Prop", String.class).invoke(bot, "helloc1");
        bottom.getMethod("addC2Prop", String.class).invoke(bot, "helloc2");
        bottom.getMethod("addC0Prop", String.class).invoke(bot, "helloc0");
        bottom.getMethod("addC0Prop", String.class).invoke(bot, "helloc0_2");

        return bot;
    }

    private void checkJaxbRefresh(Object obj, ClassLoader urlKL) {
        try {
            JAXBContext jaxbContext;
            jaxbContext = JAXBContext.newInstance(obj.getClass().getPackage().getName(), urlKL);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

            StringWriter sw = new StringWriter();
            marshaller.marshal(obj, sw);

            System.out.println(sw.toString());

            jaxbContext = JAXBContext.newInstance(obj.getClass().getPackage().getName(), urlKL);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            Marshaller marshaller2 = jaxbContext.createMarshaller();
            marshaller2.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            marshaller2.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

            Object clone = unmarshaller.unmarshal(new StringReader(sw.toString()));

            StringWriter sw2 = new StringWriter();
            marshaller2.marshal(clone, sw2);
            System.err.println(sw2.toString());

            assertEquals(sw.toString(), sw2.toString());
        } catch (PropertyException e) {
            e.printStackTrace();
            fail(e.getMessage());
        } catch (JAXBException e) {
            fail(e.getMessage());
        }
    }

    private void printSourceFile(File f, PrintStream out) {
        try {
            FileInputStream fis = new FileInputStream(f);
            byte[] buf = new byte[fis.available()];
            fis.read(buf);
            out.println(new String(buf));
        } catch (IOException ioe) {
            ioe.printStackTrace();
            fail(ioe.getMessage());
        }
    }

    private Document parseXML(File f, boolean print)
            throws IOException, ParserConfigurationException, SAXException, TransformerException {
        InputSource xSource = new InputSource(new FileInputStream(f));
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document dox = null;

        DocumentBuilder builder = dbf.newDocumentBuilder();
        dox = builder.parse(xSource);
        if (print) {
            streamXML(dox, System.out);
        }
        return dox;
    }

    private void streamXML(Document dox, PrintStream out) throws TransformerException {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(new DOMSource(dox), new StreamResult(out));
    }

    private void showDirContent(TemporaryFolder folder) {
        showDirContent(folder.getRoot(), 0);
    }

    private void showDirContent(File file, int i) {
        System.out.println(tab(i) + " " + file.getName());
        if (file.isDirectory()) {
            for (File sub : file.listFiles()) {
                showDirContent(sub, i + 1);
            }
        }
    }

    private String tab(int n) {
        return StringUtils.repeat("\t", n);
    }

}