org.semantictools.frame.api.OntologyManager.java Source code

Java tutorial

Introduction

Here is the source code for org.semantictools.frame.api.OntologyManager.java

Source

/*******************************************************************************
 * Copyright 2012 Pearson Education
 * 
 * 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.semantictools.frame.api;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.semantictools.context.renderer.model.ContextProperties;
import org.semantictools.context.renderer.model.OntologyEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.Ontology;
import com.hp.hpl.jena.rdf.model.ModelFactory;

public class OntologyManager {
    private static final String PROPERTIES_FILENAME = "asset.properties";
    private static final String URI = "uri";
    private static final String DEFAULT = "default";

    private static final String TURTLE_FORMAT = "text/turtle";
    private static final String XML_FORMAT = "text/xml";

    private static final Logger logger = LoggerFactory.getLogger(OntologyManager.class);
    private String ontologyServiceURI;

    private Map<String, OntologyEntity> uri2OntologyEntity = new HashMap<String, OntologyEntity>();
    private List<String> uploadList = new ArrayList<String>();
    private File localRepository;

    /**
     * Returns the URI to which ontology files should be uploaded.
     */
    public String getOntologyServiceURI() {
        return ontologyServiceURI;
    }

    /**
     * Returns the root directory for the local repository
     */
    public File getLocalRepository() {
        return localRepository;
    }

    /**
     * Sets the root directory for the local repository
     * @param localRepository
     */
    public void setLocalRepository(File localRepository) {
        this.localRepository = localRepository;
    }

    public void publishToLocalRepository(List<ContextProperties> contextList) {
        if (localRepository == null)
            return;
        publishSchemasToLocalRepo();
        publishJsonLdContextsToLocalRepo(contextList);
    }

    private void publishJsonLdContextsToLocalRepo(List<ContextProperties> contextList) {

        for (ContextProperties p : contextList) {
            File contextFile = p.getContextFile();
            String uri = p.getContextURI();
            if (contextFile == null || uri == null)
                continue;

            File repoDir = repoDir(uri);
            File targetFile = writeAssetPropertiesFile(repoDir, uri, LdContentType.JSON_LD_CONTEXT);
            try {
                copyFile(contextFile, targetFile);
            } catch (IOException e) {
                logger.error("Failed to copy file " + contextFile, e);
            }

        }
    }

    private void publishSchemasToLocalRepo() {

        for (OntologyEntity entity : uri2OntologyEntity.values()) {
            String uri = entity.getOntologyURI();
            File repoDir = repoDir(uri);

            LdContentType format = contentType(entity);

            File targetFile = writeAssetPropertiesFile(repoDir, uri, format);
            try {
                copyFile(entity.getFile(), targetFile);
            } catch (IOException e) {
                logger.error("Failed to copy file " + entity.getFile().getName(), e);
            }
        }

    }

    private LdContentType contentType(OntologyEntity entity) {

        return TURTLE_FORMAT.equals(entity.getContentType()) ? LdContentType.TURTLE
                : XML_FORMAT.equals(entity.getContentType()) ? LdContentType.XSD : null;
    }

    private File writeAssetPropertiesFile(File repoDir, String uri, LdContentType contentType) {
        repoDir.mkdirs();
        String format = contentType.name();
        String fileName = contentType.repoFileName();
        Properties properties = new Properties();
        properties.setProperty(URI, uri);
        properties.setProperty(DEFAULT, format);
        properties.setProperty(format, fileName);
        FileWriter writer = null;
        try {
            File file = new File(repoDir, PROPERTIES_FILENAME);
            writer = new FileWriter(file);
            properties.store(writer, null);
        } catch (Throwable oops) {
            logger.error("Failed to save properties at " + repoDir, oops);
        } finally {
            safeClose(writer);
        }
        return new File(repoDir, fileName);

    }

    private void safeClose(FileWriter writer) {
        if (writer == null)
            return;
        try {
            writer.close();
        } catch (Throwable oops) {
            logger.warn("failed to close writer", oops);
        }

    }

    private void copyFile(File sourceFile, File targetFile) throws IOException {
        InputStream input = new FileInputStream(sourceFile);

        File parent = targetFile.getParentFile();
        parent.mkdirs();
        FileOutputStream out = new FileOutputStream(targetFile);
        try {
            byte[] buffer = new byte[1024];

            int len;
            while ((len = input.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }

        } finally {
            out.close();
        }
        input.close();

    }

    private File repoDir(String assetURI) {
        try {
            URI uri = new URI(assetURI);
            String path = uri.getAuthority() + "/" + uri.getPath();

            return new File(localRepository, path);
        } catch (Throwable oops) {
            return null;
        }
    }

    /**
     * Sets the URI to which ontology files should be uploaded.
     */
    public void setOntologyServiceURI(String ontologyServiceURI) {
        this.ontologyServiceURI = ontologyServiceURI;
    }

    /**
     * Returns the list of URI values for ontologies whose Turtle or XSD files are to be uploaded 
     * to the ontology service.
     */
    public List<String> getUploadList() {
        return uploadList;
    }

    public void uploadJsonLdContextFiles(List<ContextProperties> list) {
        if (ontologyServiceURI == null)
            return;
        for (ContextProperties p : list) {
            File file = p.getContextFile();
            if (file != null) {
                try {
                    uploadFile(file, "application/ld+json");
                } catch (Throwable e) {
                    logger.warn("Failed to upload file", e);
                }
            }
        }
    }

    /**
     * Scan the specified directory for schemas, and upload them to the ontology service,
     * but only if they are included in the upload list.
     * 
     * @param rdfDir The directory that should be scanned for schema files.
     * @return The number of files uploaded.
     * @throws SchemaParseException
     * @throws IOException 
     */
    public int upload() throws SchemaParseException, IOException {
        if (ontologyServiceURI == null || uploadList.isEmpty())
            return 0;

        Collections.sort(uploadList);
        int count = 0;

        for (String ontologyURI : uploadList) {
            OntologyEntity entity = uri2OntologyEntity.get(ontologyURI);
            if (entity == null) {
                logger.warn("Cannot upload ontology because file not found: " + ontologyURI);
                continue;
            }
            try {
                uploadFile(entity.getFile(), entity.getContentType());
                count++;
            } catch (Throwable oops) {
                logger.warn("Failed to upload " + entity.getFile(), oops);
            }
        }
        return count;
    }

    private void uploadFile(File file, String contentType) throws ClientProtocolException, IOException {
        System.out.println("Uploading... " + file);

        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(ontologyServiceURI);

        FileEntity fileEntity = new FileEntity(file, contentType);
        post.setEntity(fileEntity);

        HttpResponse response = client.execute(post);
        int status = response.getStatusLine().getStatusCode();
        switch (status) {
        case HttpStatus.SC_OK:
        case HttpStatus.SC_CREATED:

            break;

        default:
            System.out.println(" ERROR: " + status);

        }
    }

    public void scan(File file) throws SchemaParseException {
        if (localRepository == null && ontologyServiceURI == null)
            return;
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                scan(child);
            }
        } else {
            String fileName = file.getName();
            if (fileName.endsWith(".xsd")) {
                loadXsd(file);
            } else if (fileName.endsWith(".ttl")) {
                loadTurtle(file);
            }
        }
    }

    private void loadTurtle(File file) throws SchemaParseException {
        if (file.getName().endsWith("_binding.ttl")) {
            // For now, ignore binding files.
            return;
        }
        try {
            OntModel model = ModelFactory.createOntologyModel();
            FileReader reader = new FileReader(file);
            model.read(reader, null, "TURTLE");

            List<Ontology> list = model.listOntologies().toList();
            if (list.isEmpty()) {
                logger.warn("Ignoring file because it contains no ontology declarations: " + file);
            } else if (list.size() == 1) {
                Ontology onto = list.get(0);
                String ontologyURI = onto.getURI();
                OntologyEntity entity = new OntologyEntity(TURTLE_FORMAT, file, ontologyURI);
                uri2OntologyEntity.put(ontologyURI, entity);

            } else {
                logger.warn("Ignoring file because it contains more than one ontology: " + file);
            }
        } catch (Throwable oops) {
            throw new SchemaParseException(oops);
        }

    }

    private void loadXsd(File file) throws SchemaParseException {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader reader = parser.getXMLReader();
            reader.setFeature("http://xml.org/sax/features/namespaces", true);
            NamespaceReader handler = new NamespaceReader();
            reader.setContentHandler(handler);

            parser.parse(file, handler);

            String namespace = handler.getTargetNamespace();
            if (namespace == null) {
                logger.warn("Ignoring schema since targetNamespace is not declared: " + file.getPath());
            } else {
                OntologyEntity entity = new OntologyEntity(XML_FORMAT, file, namespace);
                uri2OntologyEntity.put(namespace, entity);
            }
        } catch (Throwable oops) {
            throw new SchemaParseException(oops);
        }

    }

    private class NamespaceReader extends DefaultHandler {

        private String targetNamespace;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
            if ("schema".equals(localName)) {
                targetNamespace = attributes.getValue("targetNamespace");
            }
        }

        public String getTargetNamespace() {
            return targetNamespace;
        }

    }

    public enum LdContentType {

        XSD("xsd"), TURTLE("ttl"), JSON_LD_CONTEXT("json"), ENHANCED_CONTEXT("json",
                JSON_LD_CONTEXT), UNKNOWN("???");

        private String extension;
        private LdContentType defaultType;

        private LdContentType(String extension) {
            this.extension = extension;
        }

        private LdContentType(String extension, LdContentType defaultType) {
            this.extension = extension;
            this.defaultType = defaultType;
        }

        /**
         * Returns the extension that should be used for assets
         * of this content type.
         */
        public String getExtension() {
            return extension;
        }

        /**
         * Returns the content type that should be regarded as the 
         * default format for assets of this type.
         * If this content type is the default, then the return value
         * is this LdContentType instance.
         */
        public LdContentType getDefaultType() {
            return defaultType == null ? this : defaultType;
        }

        /**
         * Returns true if this content type is a default content type.
         */
        public boolean isDefaultType() {
            return defaultType == null || defaultType == this;
        }

        public String repoFileName() {
            return name() + "." + extension;
        }

        public static LdContentType guessContentType(String fileName) {
            int dot = fileName.lastIndexOf('.');
            if (dot < 0) {
                return UNKNOWN;
            }

            String suffix = fileName.substring(dot + 1);
            if (XSD.getExtension().equals(suffix))
                return XSD;
            if (TURTLE.getExtension().equals(suffix))
                return TURTLE;
            if (JSON_LD_CONTEXT.getExtension().equals(suffix))
                return JSON_LD_CONTEXT;

            return UNKNOWN;
        }
    }
}