com.kurento.kmf.orion.OrionConnector.java Source code

Java tutorial

Introduction

Here is the source code for com.kurento.kmf.orion.OrionConnector.java

Source

/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 */
package com.kurento.kmf.orion;

import static com.kurento.kmf.orion.entities.ContextUpdate.ContextUpdateAction.APPEND;
import static com.kurento.kmf.orion.entities.ContextUpdate.ContextUpdateAction.DELETE;
import static com.kurento.kmf.orion.entities.ContextUpdate.ContextUpdateAction.UPDATE;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;

import javax.annotation.PostConstruct;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.fluent.Response;
import org.apache.http.client.utils.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.gson.Gson;
import com.kurento.kmf.orion.entities.ContextUpdate;
import com.kurento.kmf.orion.entities.ContextUpdateResponse;
import com.kurento.kmf.orion.entities.OrionAttribute;
import com.kurento.kmf.orion.entities.OrionContextElement;
import com.kurento.kmf.orion.entities.QueryContext;
import com.kurento.kmf.orion.entities.QueryContextResponse;

/**
 * Connector to the ORion context broker. This connector uses only the NGSI10
 * service from Orion, and none of it's convenience methods.
 * 
 * @author Ivan Gracia (izanmail@gmail.com)
 * 
 */
public class OrionConnector {

    private static final String QUERY_PATH = "/ngsi10/queryContext";
    private static final String UPDATE_PATH = "/ngsi10/updateContext";
    private static final String SUBSCRIBE_PATH = "/ngsi10/subscribeContext";
    private static final String ENTITIES_PATH = "/ngsi10/contextEntities";
    private static final String UNSUBSCRIBE_PATH = "/ngsi10/unsubscribeContext";
    private static final String UPDATE_SUBSCRIBE_PATH = "/ngsi10/updateContextSubscription";

    private static final Gson gson = new Gson();
    private static final Logger log = LoggerFactory.getLogger(OrionConnector.class);

    @Autowired
    private OrionConnectorConfiguration config;

    private URI orionAddr;

    /**
     * Default constructor to be used when the orion connector is created from a
     * spring context.
     */
    public OrionConnector() {

    }

    /**
     * Orion connector constructor. This constructor is to be used when the
     * connector is used outside from a spring context.
     * 
     * @param config
     *            Configuration object
     */
    public OrionConnector(OrionConnectorConfiguration config) {
        this.config = config;
        this.init();
    }

    /**
     * Initiates the {@link #orionAddr}. This step is performed to validate the
     * fields from the configuration object.
     */
    @PostConstruct
    private void init() {
        try {
            orionAddr = new URIBuilder().setScheme(config.getOrionScheme()).setHost(config.getOrionHost())
                    .setPort(config.getOrionPort()).build();
        } catch (URISyntaxException e) {
            throw new OrionConnectorException("Could not build URI to make a request to Orion", e);
        }
    }

    /**
     * Register context elements in the Orion context broker.
     * 
     * @param events
     *            List of events
     * @return The response from the context broker.
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     * 
     */
    public ContextUpdateResponse registerContextElements(OrionContextElement... events) {
        ContextUpdate ctxUpdate = new ContextUpdate(APPEND, events);
        return sendRequestToOrion(ctxUpdate, UPDATE_PATH, ContextUpdateResponse.class);
    }

    /**
     * Updates context elements that exist in Orion.
     * 
     * @param events
     * @return The response from the context broker.
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     */
    public ContextUpdateResponse updateContextElements(OrionContextElement... events) {
        ContextUpdate ctxUpdate = new ContextUpdate(UPDATE, events);
        return sendRequestToOrion(ctxUpdate, UPDATE_PATH, ContextUpdateResponse.class);
    }

    /**
     * Deletes one or more context elements from Orion
     * 
     * @param events
     * @return The response from the context broker.
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     */
    public ContextUpdateResponse deleteContextElements(OrionContextElement... events) {
        ContextUpdate ctxUpdate = new ContextUpdate(DELETE, events);
        return sendRequestToOrion(ctxUpdate, UPDATE_PATH, ContextUpdateResponse.class);
    }

    /**
     * Deletes an attribute from a registered Orion context element.
     * 
     * @param element
     * @param attribute
     * @return The response from the context broker.
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     */
    public String deleteContextElementAttribute(OrionContextElement element, OrionAttribute<?> attribute) {
        // curl localhost:1026/NGSI10/contextEntities/E1/attribute/B -s -S
        // --header 'Content-Type: application/json' -X DELETE --header 'Accept:
        // application/json' | python -mjson.tool
        return null;
        // sendRemoveRequestToOrion(element.getId(), attribute.getName());
    }

    /**
     * Queries the context broker for a certain element.
     * 
     * @param type
     *            The type of context element
     * @param id
     *            the id of the context element
     * @return The response from the context broker.
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     */
    public QueryContextResponse queryContext(String type, String id) {
        OrionContextElement element = new OrionContextElement();
        element.setId(id);
        element.setType(type);
        QueryContext query = new QueryContext(element);
        return sendRequestToOrion(query, QUERY_PATH, QueryContextResponse.class);
    }

    /**
     * Queries the context broker for a pattern-based group of context elements
     * 
     * @param type
     *            the type of the context element.
     * @param pattern
     *            the pattern to search IDs that fulfil this pattern.
     * @return The response from the context broker.
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     */
    public QueryContextResponse queryContextWithPattern(String type, String pattern) {
        OrionContextElement element = new OrionContextElement();
        element.setId(pattern);
        element.setPattern(true);
        element.setType(type);
        QueryContext query = new QueryContext(element);
        return sendRequestToOrion(query, QUERY_PATH, QueryContextResponse.class);
    }

    /**
     * Sends a request to Orion
     * 
     * @param ctxElement
     *            The context element
     * @param path
     *            the path from the context broker that determines which
     *            "operation"will be executed
     * @param responseClazz
     *            The class expected for the response
     * @return The object representing the JSON answer from Orion
     * @throws OrionConnectorException
     *             if a communication exception happens, either when contacting
     *             the context broker at the given address, or obtaining the
     *             answer from it.
     */
    private <E, T> T sendRequestToOrion(E ctxElement, String path, Class<T> responseClazz) {
        String jsonEntity = gson.toJson(ctxElement);
        log.debug("Send request to Orion: {}", jsonEntity);

        Request req = Request.Post(orionAddr.toString() + path).addHeader("Accept", APPLICATION_JSON.getMimeType())
                .bodyString(jsonEntity, APPLICATION_JSON).connectTimeout(5000).socketTimeout(5000);
        Response response;
        try {
            response = req.execute();
        } catch (IOException e) {
            throw new OrionConnectorException("Could not execute HTTP request", e);
        }

        HttpResponse httpResponse = checkResponse(response);

        T ctxResp = getOrionObjFromResponse(httpResponse, responseClazz);

        log.debug("Send to Orion response: {}", httpResponse);

        return ctxResp;
    }

    private <T> HttpResponse checkResponse(Response response) {
        HttpResponse httpResponse;
        try {
            httpResponse = response.returnResponse();
        } catch (IOException e) {
            throw new OrionConnectorException("Could not obtain HTTP response", e);
        }

        if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            throw new OrionConnectorException(
                    "Failed with HTTP error code : " + httpResponse.getStatusLine().getStatusCode());
        }

        return httpResponse;
    }

    private <T> T getOrionObjFromResponse(HttpResponse httpResponse, Class<T> responseClazz) {
        InputStream source;
        try {
            source = httpResponse.getEntity().getContent();
        } catch (IllegalStateException | IOException e) {
            throw new OrionConnectorException("Could not obtain entity content from HTTP response", e);
        }

        T ctxResp = null;
        try (Reader reader = new InputStreamReader(source)) {
            ctxResp = gson.fromJson(reader, responseClazz);
        } catch (IOException e) {
            log.warn("Could not close input stream from HttpResponse.", e);
        }

        return ctxResp;
    }

    // contextEntities consultas a entidades, borrados...
    // queryContext
    // notifyContext notifyContextRequest notifyContextResponse
    // updateContext

    // queryContext access the context information stored. con lista de
    // atributos
    // devuelve slo los atributos deseados
    // contextEntities

    /*-
     *   subscribeContext
     *   updateContextSubscription
     *   unsubscribeContext
     * 
     * (curl localhost:1026/NGSI10/subscribeContext -s -S 
     *  --header 'Content-Type: application/json' 
     *  --header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
     *   {
     *      "entities": [
     *        {
     *            "type": "Room",
     *            "isPattern": "false",
     *            "id": "Room1"
     *         }
     *      ],
     *      "attributes": [
     *         "temperature"
     *      ],
     *      "reference": "http://localhost:1028/accumulate",
     *      "duration": "P1M",
     *      "notifyConditions": [
     *         {
     *            "type": "ONTIMEINTERVAL",
     *            "condValues": [
     *            "PT10S"
     *            ]
     *         }
     *      ]
     *   }
     *   EOF
     */
}