/* * This software is Copyright 2005,2006,2007,2008 Langdale Consultants. * Langdale Consultants can be contacted at: http://www.langdale.com.au */ package au.com.langdale.cimtoole.builder; import java.io.IOException; import java.util.Collection; import java.util.Collections; import javax.xml.transform.Source; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.SchemaFactory; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.xml.sax.SAXException; import au.com.langdale.cimtoole.CIMToolPlugin; import au.com.langdale.cimtoole.project.Cache; import au.com.langdale.cimtoole.project.Task; import au.com.langdale.cimtoole.registries.ProfileBuildletRegistry; import au.com.langdale.jena.OntModelProvider; import au.com.langdale.kena.OntModel; import au.com.langdale.kena.Resource; import au.com.langdale.kena.ResourceFactory; import au.com.langdale.profiles.MESSAGE; import au.com.langdale.profiles.OWLGenerator; import au.com.langdale.profiles.ProfileModel; import au.com.langdale.profiles.ProfileSerializer; import au.com.langdale.profiles.RDFSBasedGenerator; import au.com.langdale.profiles.RDFSGenerator; import au.com.langdale.ui.binding.BooleanModel; import au.com.langdale.workspace.ResourceOutputStream; import com.hp.hpl.jena.vocabulary.RDF; /** * A series of <code>Buildlet</code>s for building profile artifacts. */ public class ProfileBuildlets extends Task { /** * Buildlet for a profile artifact. * * Each type of profile buildlet is characterised by a specific file type * and a flag in the profile that enables it. */ public abstract static class ProfileBuildlet extends Buildlet { private String ext; protected ProfileBuildlet(String fileType) { ext = fileType; } @Override protected Collection getOutputs(IResource file) throws CoreException { if (isProfile(file)) return Collections .singletonList(getRelated(file, getFileType())); else return Collections.EMPTY_LIST; } public BooleanModel getFlag(final OntModelProvider context) { return new BooleanModel() { public boolean isTrue() { OntModel model = context.getModel(); return model != null && isFlagged(model); } public void setTrue(boolean flag) { OntModel model = context.getModel(); if (model != null) setFlagged(model, flag); } @Override public String toString() { return "Builder for " + getFileType(); } }; } public Resource getIdentifier() { return ResourceFactory.createResource(NS + getFileType()); } public String getFileType() { return ext; } public boolean isFlagged(IFile file) throws CoreException { Cache cache = CIMToolPlugin.getCache(); OntModel model = cache.getOntologyWait(file); return model != null && isFlagged(model); } public boolean isFlagged(OntModel model) { return model.contains(getIdentifier(), RDF.type, MESSAGE.Flag); } public void setFlagged(OntModel model, boolean flag) { if (flag) model.add(getIdentifier(), RDF.type, MESSAGE.Flag); else model.remove(getIdentifier(), RDF.type, MESSAGE.Flag); } @Override public void run(IFile result, boolean cleanup, IProgressMonitor monitor) throws CoreException { IFile file = getRelated(result, "owl"); if (cleanup || !file.exists() || !isFlagged(file)) clean(result, monitor); else build(result, monitor); } } /** * Buildlet that merely outputs the profile in a different language. */ public static class CopyBuildlet extends ProfileBuildlet { private String format; public CopyBuildlet(String format, String ext) { super(ext); this.format = format; } @Override protected void build(IFile result, IProgressMonitor monitor) throws CoreException { IFile file = getRelated(result, "owl"); OntModel model = getProfileModel(file); writeOntology(result, model, format, monitor); } } /** * Buildlet for a profile artifact that is the product of an XSLT transform. */ public static class TransformBuildlet extends ProfileBuildlet { private String style; public TransformBuildlet(String style, String ext) { super(ext); this.style = style; } @Override protected Collection getOutputs(IResource file) throws CoreException { if (isProfile(file) || isRuleSet(file, style + "-xslt") && isProfile(getRelated(file, "owl"))) return Collections .singletonList(getRelated(file, getFileType())); else return Collections.EMPTY_LIST; } protected void setupPostProcessors(ProfileSerializer serializer) throws TransformerConfigurationException { } @Override protected void build(IFile result, IProgressMonitor monitor) throws CoreException { IFile file = getRelated(result, "owl"); ProfileModel tree = getMessageModel(file); ProfileSerializer serializer = new ProfileSerializer(tree); try { serializer.setBaseURI(tree.getNamespace()); // TODO: make this better serializer.setVersion("Beta"); IFile local = getRelated(result, style + "-xslt"); if (local.exists()) { serializer.setErrorHandler(CIMBuilder .createErrorHandler(local)); serializer.setStyleSheet(local.getContents(), ProfileSerializer.XSDGEN); } else { serializer.setStyleSheet(style); } setupPostProcessors(serializer); } catch (TransformerConfigurationException e) { error("error parsing XSLT script", e); } try { ResourceOutputStream ostream = new ResourceOutputStream(result, monitor, false, true); serializer.write(ostream); ostream.close(); } catch (TransformerException e) { error("error transforming profile", e); } catch (IOException e) { error("error writing output", e); } } } /** * Buildlet for XML Schema profiles. * * The basic XSLT transform is followed by XML Schema validation. */ public static class XSDBuildlet extends TransformBuildlet { public XSDBuildlet() { this("xsd"); } public XSDBuildlet(String style) { super(style, "xsd"); } @Override protected void build(IFile result, IProgressMonitor monitor) throws CoreException { super.build(result, monitor); SchemaFactory parser = SchemaFactory .newInstance("http://www.w3.org/2001/XMLSchema"); parser.setErrorHandler(CIMBuilder.createErrorHandler(result)); Source source = new StreamSource(result.getContents()); try { parser.newSchema(source); } catch (SAXException e) { throw error("error validating generated schema", e); } } } /** * Buildlet for java artifacts. */ public static class TextBuildlet extends TransformBuildlet { public TextBuildlet(String style, String ext) { super(style, ext); } @Override protected void setupPostProcessors(ProfileSerializer serializer) throws TransformerConfigurationException { serializer.addStyleSheet("indent"); } } /** * Buildlet for profile artifacts that are related to the simplified RDFS * representation. */ public static abstract class RDFSBasedBuildlet extends ProfileBuildlet { private String lang; protected boolean withInverses; protected RDFSBasedBuildlet(String lang, String fileType, boolean withInverses) { super(fileType); this.lang = lang; this.withInverses = withInverses; } @Override protected void build(IFile result, IProgressMonitor monitor) throws CoreException { IFile file = getRelated(result, "owl"); boolean preserveNS = getPreferenceOption(PRESERVE_NAMESPACES); OntModel profileModel = getProfileModel(file); OntModel backgroundModel = getBackgroundModel(file); RDFSBasedGenerator generator = getGenerator(profileModel, backgroundModel, preserveNS); generator.run(); OntModel resultModel = generator.getResult(); System.out .println("Generated ontology size: " + resultModel.size()); Task.write(resultModel, generator.getOntURI(), true, result, lang, monitor); result.setDerived(true); } protected abstract RDFSBasedGenerator getGenerator( OntModel profileModel, OntModel backgroundModel, boolean preserveNS) throws CoreException; } /** * Buildlet for the simple OWL representation of the profile. */ public static class SimpleOWLBuildlet extends RDFSBasedBuildlet { public SimpleOWLBuildlet(String lang, String fileType, boolean withInverses) { super(lang, fileType, withInverses); } @Override protected RDFSBasedGenerator getGenerator(OntModel profileModel, OntModel backgroundModel, boolean preserveNS) throws CoreException { return new OWLGenerator(profileModel, backgroundModel, preserveNS, withInverses); } } /** * Buildlet for a profile in the original IEC RDFS language. */ public static class LegacyRDFSBuildlet extends RDFSBasedBuildlet { public LegacyRDFSBuildlet(String lang, String fileType, boolean withInverses) { super(lang, fileType, withInverses); } @Override protected RDFSBasedGenerator getGenerator(OntModel profileModel, OntModel backgroundModel, boolean preserveNS) throws CoreException { return new RDFSGenerator(profileModel, backgroundModel, preserveNS, withInverses); } } public static BooleanModel[] getAvailable(OntModelProvider context) { ProfileBuildlet[] buildlets = getAvailable(); BooleanModel[] flags = new BooleanModel[buildlets.length]; for (int ix = 0; ix < buildlets.length; ix++) flags[ix] = buildlets[ix].getFlag(context); return flags; } /** * @return: a list of all profile buildlets. */ private static ProfileBuildlet[] getAvailable() { ProfileBuildlet[] defaultBuildlets = new ProfileBuildlet[] { new XSDBuildlet(), new TransformBuildlet(null, "xml"), new TransformBuildlet("html", "html"), new TextBuildlet("sql", "sql"), new TextBuildlet("scala", "scala"), new TextBuildlet("jpa", "java"), new SimpleOWLBuildlet("RDF/XML", "simple-flat-owl", false), new SimpleOWLBuildlet("RDF/XML-ABBREV", "simple-owl", false), new LegacyRDFSBuildlet("RDF/XML", "legacy-rdfs", false), new SimpleOWLBuildlet("RDF/XML", "simple-flat-owl-augmented", true), new SimpleOWLBuildlet("RDF/XML-ABBREV", "simple-owl-augmented", true), new LegacyRDFSBuildlet("RDF/XML", "legacy-rdfs-augmented", true), new CopyBuildlet("TURTLE", "ttl") }; ProfileBuildlet[] registered = ProfileBuildletRegistry.INSTANCE.getBuildlets(); if (registered.length>0){ ProfileBuildlet[] combined = new ProfileBuildlet[defaultBuildlets.length+registered.length]; System.arraycopy(defaultBuildlets, 0, combined, 0, defaultBuildlets.length); System.arraycopy(registered, 0, combined, defaultBuildlets.length, registered.length); return combined; }else return defaultBuildlets; } }