de.badw.strauss.glyphpicker.controller.alltab.TeiLoadWorker.java Source code

Java tutorial

Introduction

Here is the source code for de.badw.strauss.glyphpicker.controller.alltab.TeiLoadWorker.java

Source

/**
 * Copyright 2015 Alexander Erhard
 *
 * 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 de.badw.strauss.glyphpicker.controller.alltab;

import com.icl.saxon.aelfred.SAXParserFactoryImpl;
import de.badw.strauss.glyphpicker.model.DataSource;
import de.badw.strauss.glyphpicker.model.GlyphDefinition;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.log4j.Logger;
import org.xml.sax.SAXException;

import javax.swing.*;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

/**
 * A worker loading glyph definitions from a document or online resource.
 */
public class TeiLoadWorker extends SwingWorker<List<GlyphDefinition>, Void> {

    /**
     * The logger.
     */
    private static final Logger LOGGER = Logger.getLogger(TeiLoadWorker.class.getName());

    /**
     * The data source object providing the loading parameters.
     */
    private final DataSource dataSource;
    /**
     * The i18n resource bundle.
     */
    private final ResourceBundle i18n;
    /**
     * The loading result, a list of GlyphDefinition objects.
     */
    private List<GlyphDefinition> result = null;
    /**
     * The SAX parser.
     */
    private SAXParser parser;

    /**
     * Instantiates a new TeiLoadWorker.
     *
     * @param dataSource The data source object providing the loading parameters
     */
    public TeiLoadWorker(DataSource dataSource) {
        this.dataSource = dataSource;

        i18n = ResourceBundle.getBundle("GlyphPicker");

        SAXParserFactory parserFactory = SAXParserFactoryImpl.newInstance();
        try {
            parser = parserFactory.newSAXParser();
        } catch (ParserConfigurationException e) {
            LOGGER.error(e);
        } catch (SAXException e) {
            LOGGER.error(e);
        }
    }

    /**
     * returns the resulting glyph list.
     *
     * @return the result list
     */
    public List<GlyphDefinition> getResult() {
        return result;
    }

    /* (non-Javadoc)
     * @see javax.swing.SwingWorker#doInBackground()
     */
    @Override
    protected List<GlyphDefinition> doInBackground() {
        return loadData();
    }

    /* (non-Javadoc)
     * @see javax.swing.SwingWorker#done()
     */
    @Override
    protected void done() {
        try {
            result = get();
        } catch (InterruptedException e) {
            LOGGER.error(e);
        } catch (ExecutionException e) {
            LOGGER.error(e);
        } catch (CancellationException e) {
            LOGGER.error(e);
        }
    }

    /**
     * Load data.
     *
     * @return the list
     */
    public List<GlyphDefinition> loadData() {
        String path = dataSource.getBasePath();
        return (isLocalFile(path)) ? loadDataFromFile() : loadDataFromUrl();
    }

    /**
     * Checks if the provided path points to a local file.
     *
     * @param path the path
     * @return the result
     */
    private Boolean isLocalFile(String path) {
        return (!path.matches("^\\w+://.*"));
    }

    /**
     * Loads TEI data from a URL.
     *
     * @return the resulting GlyphDefinition list
     */
    public List<GlyphDefinition> loadDataFromUrl() {
        SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient();
        try {
            HttpGet httpGet = new HttpGet(dataSource.getBasePath());
            return httpClient.execute(httpGet, new XMLResponseHandler());
        } catch (IOException e) {
            String message = String.format(i18n.getString("TeiLoadWorker.couldNotLoadData"),
                    e.getLocalizedMessage(), dataSource.getBasePath());
            if (e instanceof UnknownHostException) {
                message += " Unknown host";
            }
            JOptionPane.showMessageDialog(null, message, i18n.getString("TeiLoadWorker.error"),
                    JOptionPane.ERROR_MESSAGE);
            LOGGER.info(e);
        } finally {
            httpClient.getConnectionManager().shutdown();
        }

        return null;
    }

    /**
     * Loads data from a file.
     *
     * @return the resulting GlyphDefinition list
     */
    public List<GlyphDefinition> loadDataFromFile() {

        String fileName = dataSource.getBasePath();

        if (fileName != null) {
            File file = new File(fileName);
            InputStream inputStream = null;

            try {
                inputStream = new FileInputStream(file);
            } catch (IOException e) {
                JOptionPane.showMessageDialog(
                        null, String.format(i18n.getString("TeiLoadWorker.couldNotLoadData"),
                                e.getLocalizedMessage(), fileName),
                        i18n.getString("TeiLoadWorker.error"), JOptionPane.ERROR_MESSAGE);
                LOGGER.info(e);
            }
            if (inputStream != null) {
                return parseXmlSax(inputStream);
            }
        }
        return null;
    }

    /**
     * Triggers parsing of the XML input stream.
     *
     * @param is the input stream
     * @return the resulting GlyphDefinition list
     */
    public List<GlyphDefinition> parseXmlSax(InputStream is) {
        TeiXmlHandler handler = new TeiXmlHandler(dataSource);
        try {
            parser.parse(is, handler);
            handler.resolveReferences();
            return handler.getGlyphDefinitions();
        } catch (SAXException e) {
            JOptionPane.showMessageDialog(null, e.toString(), i18n.getString("TeiLoadWorker.xmlParsingError"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, e.toString(), i18n.getString("TeiLoadWorker.xmlParsingError"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (TeiXmlHandler.RecursionException e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), i18n.getString("TeiLoadWorker.xmlParsingError"),
                    JOptionPane.ERROR_MESSAGE);
        }
        return null;
    }

    /**
     * The XML response handler.
     */
    private class XMLResponseHandler implements ResponseHandler<List<GlyphDefinition>> {

        /* (non-Javadoc)
         * @see org.apache.http.client.ResponseHandler#handleResponse(org.apache.http.HttpResponse)
         */
        @Override
        public List<GlyphDefinition> handleResponse(final HttpResponse response) throws IOException {
            StatusLine statusLine = response.getStatusLine();
            HttpEntity entity = response.getEntity();
            if (statusLine.getStatusCode() >= 300) {
                throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
            }
            if (entity == null) {
                throw new ClientProtocolException("Response contains no content");
            }

            InputStream inputStream = entity.getContent();

            return parseXmlSax(inputStream);
        }
    }

}