org.apache.streams.datasift.provider.DatasiftPushProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.streams.datasift.provider.DatasiftPushProvider.java

Source

/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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.apache.streams.datasift.provider;

import com.datasift.client.stream.DeletedInteraction;
import com.datasift.client.stream.StreamEventListener;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import org.apache.streams.core.StreamsDatum;
import org.apache.streams.core.StreamsProvider;
import org.apache.streams.core.StreamsResultSet;
import org.apache.streams.datasift.Datasift;
import org.apache.streams.datasift.DatasiftConfiguration;
import org.apache.streams.datasift.DatasiftWebhookData;
import org.apache.streams.jackson.StreamsJacksonMapper;
import org.apache.streams.util.ComponentUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Pattern;

/**
 * {@code DatasiftPushProvider} is an implementation of the {@link org.apache.streams.core.StreamsProvider} interface, with
 * annotations that allow it to bind as jersey resources within streams-runtime-dropwizard.
 *
 * Whereas GenericWebhookResource outputs ObjectNode datums, DatasiftPushProvider outputs Datasift datums, with
 * metadata when the json_meta endpoint is used.
 */
@Resource
@Path("/streams/webhooks/datasift")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DatasiftPushProvider implements StreamsProvider {

    private final static Logger LOGGER = LoggerFactory.getLogger(DatasiftPushProvider.class);

    private static ObjectMapper mapper = StreamsJacksonMapper.getInstance();

    protected Queue<StreamsDatum> providerQueue = new ConcurrentLinkedQueue<>();

    protected final ReadWriteLock lock = new ReentrantReadWriteLock();

    private static Pattern newLinePattern = Pattern.compile("(\\r\\n?|\\n)", Pattern.MULTILINE);

    @POST
    @Path("json")
    public Response json(@Context HttpHeaders headers, String body) {

        ObjectNode response = mapper.createObjectNode();

        StreamsDatum datum = new StreamsDatum(body);

        lock.writeLock().lock();
        ComponentUtils.offerUntilSuccess(datum, providerQueue);
        lock.writeLock().unlock();

        Boolean success = true;

        response.put("success", success);

        return Response.status(200).entity(response).build();

    }

    @POST
    @Path("json_new_line")
    public Response json_new_line(@Context HttpHeaders headers, String body) {

        ObjectNode response = mapper.createObjectNode();

        if (body.equalsIgnoreCase("{}")) {

            Boolean success = true;

            response.put("success", success);

            return Response.status(200).entity(response).build();
        }

        try {

            for (String item : Splitter.on(newLinePattern).split(body)) {
                StreamsDatum datum = new StreamsDatum(item);

                lock.writeLock().lock();
                ComponentUtils.offerUntilSuccess(datum, providerQueue);
                lock.writeLock().unlock();

            }

            Boolean success = true;

            response.put("success", success);

            return Response.status(200).entity(response).build();

        } catch (Exception e) {
            LOGGER.warn(e.toString(), e);

            Boolean success = false;

            response.put("success", success);

            return Response.status(500).entity(response).build();

        }

    }

    @POST
    @Path("json_meta")
    public Response json_meta(@Context HttpHeaders headers, String body) {

        //log.debug(headers.toString(), headers);

        //log.debug(body.toString(), body);

        ObjectNode response = mapper.createObjectNode();

        if (body.equalsIgnoreCase("{}")) {

            Boolean success = true;

            response.put("success", success);

            return Response.status(200).entity(response).build();
        }

        try {

            DatasiftWebhookData objectWrapper = mapper.readValue(body, DatasiftWebhookData.class);

            for (Datasift item : objectWrapper.getInteractions()) {

                String json = mapper.writeValueAsString(item);

                StreamsDatum datum = new StreamsDatum(json);
                if (item.getInteraction() != null && !Strings.isNullOrEmpty(item.getInteraction().getId())) {
                    datum.setId(item.getInteraction().getId());
                }
                if (item.getInteraction() != null && item.getInteraction().getCreatedAt() != null) {
                    datum.setTimestamp(item.getInteraction().getCreatedAt());
                }
                Map<String, Object> metadata = Maps.newHashMap();
                metadata.put("hash", objectWrapper.getHash());
                metadata.put("hashType", objectWrapper.getHashType());
                metadata.put("id", objectWrapper.getId());

                if (item.getInteraction() != null && item.getInteraction().getTags() != null
                        && item.getInteraction().getTags().size() > 0) {
                    metadata.put("tags", item.getInteraction().getTags());
                }

                datum.setMetadata(metadata);

                lock.writeLock().lock();
                ComponentUtils.offerUntilSuccess(datum, providerQueue);
                lock.writeLock().unlock();
            }

            Boolean success = true;

            response.put("success", success);

            return Response.status(200).entity(response).build();

        } catch (Exception e) {
            LOGGER.warn(e.toString(), e);
        }

        return Response.status(500).build();
    }

    @Override
    public void startStream() {
        return;
    }

    @Override
    public StreamsResultSet readCurrent() {

        StreamsResultSet current;

        lock.writeLock().lock();
        current = new StreamsResultSet(Queues.newConcurrentLinkedQueue(providerQueue));
        providerQueue.clear();
        lock.writeLock().unlock();

        return current;

    }

    @Override
    public StreamsResultSet readNew(BigInteger sequence) {
        return null;
    }

    @Override
    public StreamsResultSet readRange(DateTime start, DateTime end) {
        return null;
    }

    @Override
    public boolean isRunning() {
        return true;
    }

    @Override
    public void prepare(Object configurationObject) {

    }

    @Override
    public void cleanUp() {

    }

}