com.sdl.odata.unmarshaller.atom.AtomLinkUnmarshaller.java Source code

Java tutorial

Introduction

Here is the source code for com.sdl.odata.unmarshaller.atom.AtomLinkUnmarshaller.java

Source

/**
 * Copyright (c) 2014 All Rights Reserved by the SDL Group.
 *
 * 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 com.sdl.odata.unmarshaller.atom;

import com.sdl.odata.api.ODataSystemException;
import com.sdl.odata.api.service.MediaType;
import com.sdl.odata.api.service.ODataRequestContext;
import com.sdl.odata.api.unmarshaller.ODataUnmarshallingException;
import com.sdl.odata.unmarshaller.AbstractLinkUnmarshaller;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

import static com.sdl.odata.AtomConstants.ID;
import static com.sdl.odata.AtomConstants.REF;
import static com.sdl.odata.util.ReferenceUtil.isNullOrEmpty;

/**
 * Unmarshaller for POST and PUT requests where the URI is reference (it ends in ".../$ref"). The body of such a
 * request is expected to contain an entity reference in Atom XML format. This unmarshaller returns an ODataLink object
 * containing information about the link to be created.
 * <p>
 * See OData v4 specification part 1, paragraph 11.4.6 Modifying Relationships between Entities
 * See OData v4 Atom XML format specification, chapter 13 Entity Reference
 */
@Component
public class AtomLinkUnmarshaller extends AbstractLinkUnmarshaller {
    private static final MediaType[] SUPPORTED_MEDIA_TYPES = { MediaType.ATOM_XML, MediaType.XML };

    @Override
    protected MediaType[] supportedMediaTypes() {
        return SUPPORTED_MEDIA_TYPES;
    }

    @Override
    protected String getToEntityId(ODataRequestContext requestContext) throws ODataUnmarshallingException {
        // The body is expected to contain a single entity reference
        // See OData Atom XML specification chapter 13

        String bodyText;
        try {
            bodyText = requestContext.getRequest().getBodyText(StandardCharsets.UTF_8.name());
        } catch (UnsupportedEncodingException e) {
            throw new ODataSystemException("UTF-8 is not supported", e);
        }

        Document document = parseXML(bodyText);
        Element rootElement = document.getDocumentElement();
        if (!rootElement.getNodeName().equals(REF)) {
            throw new ODataUnmarshallingException("A " + requestContext.getRequest().getMethod()
                    + " request to an entity reference URI must contain a single entity reference in the body,"
                    + " but something else was found instead: " + rootElement.getNodeName());
        }

        String idAttr = rootElement.getAttribute(ID);
        if (isNullOrEmpty(idAttr)) {
            throw new ODataUnmarshallingException("The <metadata:ref> element in the body has no 'id' attribute,"
                    + " or the attribute is empty. The element must have an 'id' attribute that refers"
                    + " to the entity to link to.");
        }

        return idAttr;
    }

    private Document parseXML(String xml) throws ODataUnmarshallingException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);

        try {
            return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
        } catch (SAXException e) {
            throw new ODataUnmarshallingException("Error while parsing XML", e);
        } catch (IOException | ParserConfigurationException e) {
            throw new ODataSystemException(e);
        }
    }
}