org.dswarm.graph.resources.XMLResource.java Source code

Java tutorial

Introduction

Here is the source code for org.dswarm.graph.resources.XMLResource.java

Source

/**
 * This file is part of d:swarm graph extension.
 *
 * d:swarm graph extension is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * d:swarm graph extension is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with d:swarm graph extension.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.dswarm.graph.resources;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Optional;
import org.neo4j.graphdb.GraphDatabaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.dswarm.common.DMPStatics;
import org.dswarm.common.model.AttributePath;
import org.dswarm.common.model.util.AttributePathUtil;
import org.dswarm.graph.DMPGraphException;
import org.dswarm.graph.index.NamespaceIndex;
import org.dswarm.graph.tx.Neo4jTransactionHandler;
import org.dswarm.graph.tx.TransactionHandler;
import org.dswarm.graph.xml.read.PropertyGraphXMLReader;
import org.dswarm.graph.xml.read.XMLReader;

/**
 * TODO: refactor the design of the resources. this is not RESTy atm, i.e., there should be one pattern how the receive a certain
 * data model from this unmanaged extension and depending on the Accept-Type of the request the result will be in this format
 * (media type), i.e., "gdm", various RDF serialisation, XML, or whatever ... => i.e., we don't need separate resources
 * (endpoints) for certain descriptions (abstract formats) or representations (concrete formats, mediatypes, serialisations)
 *
 * @author tgaengler
 */
@Path("/xml")
public class XMLResource {

    private static final Logger LOG = LoggerFactory.getLogger(XMLResource.class);

    /**
     * The object mapper that can be utilised to de-/serialise JSON nodes.
     */
    private final ObjectMapper objectMapper;

    public XMLResource() {

        objectMapper = new ObjectMapper();
    }

    @GET
    @Path("/ping")
    public String ping() {

        XMLResource.LOG.debug("ping was called");

        return "pong";
    }

    @POST
    @Path("/get")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_XML)
    public Response readXML(final String jsonObjectString, @Context final GraphDatabaseService database)
            throws DMPGraphException {

        XMLResource.LOG.debug("try to read XML records from graph db");

        final ObjectNode json;

        try {

            json = objectMapper.readValue(jsonObjectString, ObjectNode.class);
        } catch (final IOException e) {

            final String message = "could not deserialise request JSON for read from graph DB request";

            XMLResource.LOG.debug(message);

            throw new DMPGraphException(message, e);
        }

        final String recordClassUri = json.get(DMPStatics.RECORD_CLASS_URI_IDENTIFIER).asText();
        final String dataModelUri = json.get(DMPStatics.DATA_MODEL_URI_IDENTIFIER).asText();
        final JsonNode rootAttributePathNode = json.get(DMPStatics.ROOT_ATTRIBUTE_PATH_IDENTIFIER);
        final Optional<AttributePath> optionalRootAttributePath = Optional
                .fromNullable(AttributePathUtil.parseAttributePathNode(rootAttributePathNode));

        final Optional<String> optionalRecordTag;

        final JsonNode recordTagNode = json.get(DMPStatics.RECORD_TAG_IDENTIFIER);

        if (recordTagNode != null) {

            optionalRecordTag = Optional.fromNullable(recordTagNode.asText());
        } else {

            optionalRecordTag = Optional.absent();
        }

        final JsonNode versionNode = json.get(DMPStatics.VERSION_IDENTIFIER);
        final Optional<Integer> optionalVersion;

        if (versionNode != null) {

            optionalVersion = Optional.fromNullable(versionNode.asInt());
        } else {

            optionalVersion = Optional.absent();
        }

        final JsonNode allVersionsNode = json.get(DMPStatics.ALL_VERSIONS_IDENTIFIER);
        final Optional<Boolean> optionalAllversion;

        if (allVersionsNode != null) {

            optionalAllversion = Optional.fromNullable(allVersionsNode.asBoolean());
        } else {

            optionalAllversion = Optional.absent();
        }

        final Optional<JsonNode> optionalOriginalDataTypeNode = Optional
                .fromNullable(json.get(DMPStatics.ORIGINAL_DATA_TYPE_IDENTIFIER));

        final Optional<String> optionalOriginalDataType;

        if (optionalOriginalDataTypeNode.isPresent()) {

            final Optional<String> optionalOriginalDataTypeFromJSON = Optional
                    .fromNullable(optionalOriginalDataTypeNode.get().asText());

            if (optionalOriginalDataTypeFromJSON.isPresent()) {

                optionalOriginalDataType = optionalOriginalDataTypeFromJSON;
            } else {

                optionalOriginalDataType = Optional.absent();
            }
        } else {

            optionalOriginalDataType = Optional.absent();
        }

        LOG.debug("try to read XML records for data model uri = '{}' and record class uri = '{}' from graph db",
                dataModelUri, recordClassUri);

        final TransactionHandler tx = new Neo4jTransactionHandler(database);
        final NamespaceIndex namespaceIndex = new NamespaceIndex(database, tx);

        final XMLReader xmlReader = new PropertyGraphXMLReader(optionalRootAttributePath, optionalRecordTag,
                recordClassUri, dataModelUri, optionalVersion, optionalAllversion, optionalOriginalDataType,
                database, tx, namespaceIndex);

        final StreamingOutput stream = new StreamingOutput() {

            @Override
            public void write(final OutputStream os) throws IOException, WebApplicationException {

                try {

                    final BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
                    final Optional<XMLStreamWriter> optionalWriter = xmlReader.read(bos);

                    if (optionalWriter.isPresent()) {

                        optionalWriter.get().flush();
                        optionalWriter.get().close();

                        LOG.debug(
                                "finished reading '{}' XML records for data model uri = '{}' and record class uri = '{}' from graph db",
                                xmlReader.recordCount(), dataModelUri, recordClassUri);
                    } else {

                        bos.close();
                        os.close();

                        LOG.debug(
                                "couldn't find any XML records for data model uri = '{}' and record class uri = '{}' from graph db",
                                dataModelUri, recordClassUri);
                    }
                } catch (final DMPGraphException | XMLStreamException e) {

                    throw new WebApplicationException(e);
                }
            }
        };

        return Response.ok(stream, MediaType.APPLICATION_XML_TYPE).build();
    }
}