io.orchestrate.client.EventFetchOperation.java Source code

Java tutorial

Introduction

Here is the source code for io.orchestrate.client.EventFetchOperation.java

Source

/*
 * Copyright 2013 the original author or authors.
 *
 * 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 io.orchestrate.client;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.glassfish.grizzly.http.HttpHeader;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static io.orchestrate.client.Preconditions.*;

/**
 * Fetch events for a key in the Orchestrate.io service.
 *
 * <p>Usage:
 * <pre>
 * {@code
 * EventFetchOperation<MyObject> eventFetchOp =
 *         new EventFetchOperation<MyObject>("myCollection", "someKey", "eventType", MyObject.class);
 * Future<Iterable<Event<MyObject>> futureResult = client.execute(eventFetchOp);
 * Iterable<Event<MyObject>> results = futureResult.get();
 * for (Event<MyObject> event : results)
 *     System.out.println(event.getTimestamp());
 * }
 * </pre>
 *
 * @param <T> The type to deserialize the result of this operation to.
 * @see <a href="http://java.orchestrate.io/querying/#fetch-events">http://java.orchestrate.io/querying/#fetch-events</a>
 */
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public final class EventFetchOperation<T> extends AbstractOperation<Iterable<Event<T>>> {

    /** The collection containing the key. */
    private final String collection;
    /** The key to query for events. */
    private final String key;
    /** The type of events to query. */
    private final String type;
    /** The timestamp to get events from. */
    private final Long start;
    /** The timestamp to get events up to. */
    private final Long end;
    /** Type information for marshalling objects at runtime. */
    private final Class<T> clazz;

    /**
     * Create a new {@code EventFetchOperation} to get events of the specified
     * {@code type} from the {@code key} in the {@code collection}.
     *
     * @param collection The collection containing the key.
     * @param key The key to query for events.
     * @param type The type of event.
     * @param clazz Type information for deserializing to type {@code T} at
     *              runtime.
     */
    public EventFetchOperation(final String collection, final String key, final String type, final Class<T> clazz) {
        this.collection = checkNotNullOrEmpty(collection, "collection");
        this.key = checkNotNullOrEmpty(key, "key");
        this.type = checkNotNullOrEmpty(type, "type");
        this.start = null;
        this.end = null;
        this.clazz = checkNotNull(clazz, "clazz");
    }

    /**
     * Create a new {@code EventFetchOperation} to get events of the specified
     * {@code type} from the {@code key} in the {@code collection} from the
     * {@code start} point in time.
     *
     * @param collection The collection containing the key.
     * @param key The key to query for events.
     * @param type The type of event.
     * @param start The start point to get events from.
     * @param clazz Type information for deserializing to type {@code T} at
     *              runtime.
     */
    public EventFetchOperation(final String collection, final String key, final String type, final long start,
            final Class<T> clazz) {
        checkArgument(start >= 0, "'start' cannot be negative.");

        this.collection = checkNotNullOrEmpty(collection, "collection");
        this.key = checkNotNullOrEmpty(key, "key");
        this.type = checkNotNullOrEmpty(type, "type");
        this.start = start;
        this.end = null;
        this.clazz = checkNotNull(clazz, "clazz");
    }

    /**
     * Create a new {@code EventFetchOperation} to get events of the specified
     * {@code type} from the {@code key} in the {@code collection} between the
     * {@code start} and {@code end} range.
     *
     * @param collection The collection containing the key.
     * @param key The key to query for events.
     * @param type The type of event.
     * @param start The start point to get events from.
     * @param end The end point to get events up to.
     * @param clazz Type information for deserializing to type {@code T} at
     *              runtime.
     */
    public EventFetchOperation(final String collection, final String key, final String type, final long start,
            final long end, final Class<T> clazz) {
        checkArgument(start >= 0, "'start' cannot be negative.");
        checkArgument(end >= 0, "'end' cannot be negative.");

        this.collection = checkNotNullOrEmpty(collection, "collection");
        this.key = checkNotNullOrEmpty(key, "key");
        this.type = checkNotNullOrEmpty(type, "type");
        this.start = start;
        this.end = end;
        this.clazz = checkNotNull(clazz, "clazz");
    }

    /** {@inheritDoc} */
    @Override
    @SuppressWarnings("unchecked")
    Iterable<Event<T>> fromResponse(final int status, final HttpHeader httpHeader, final String json,
            final JacksonMapper mapper) throws IOException {
        assert (status == 200);

        final ObjectMapper objectMapper = mapper.getMapper();
        final JsonNode jsonNode = objectMapper.readTree(json);

        final int count = jsonNode.get("count").asInt();
        final List<Event<T>> events = new ArrayList<Event<T>>(count);

        final Iterator<JsonNode> iter = jsonNode.get("results").elements();
        while (iter.hasNext()) {
            final JsonNode result = iter.next();

            final long timestamp = result.get("timestamp").asLong();

            final JsonNode valueNode = result.get("value");
            final String rawValue = valueNode.toString();

            final T value;
            if (clazz == String.class) {
                // don't deserialize JSON data
                value = (T) rawValue;
            } else {
                value = objectMapper.readValue(rawValue, clazz);
            }

            events.add(new Event<T>(value, rawValue, timestamp));
        }
        return events;
    }

    /**
     * Returns the collection from this operation.
     *
     * @return The collection from this operation.
     */
    public String getCollection() {
        return collection;
    }

    /**
     * Returns the key from this operation.
     *
     * @return The key from this operation.
     */
    public String getKey() {
        return key;
    }

    /**
     * Returns the type from this operation.
     *
     * @return The type from this operation.
     */
    public String getType() {
        return type;
    }

    /**
     * Returns the start timestamp from this operation.
     *
     * @return The start timestamp from this operation, may be {@code null}.
     * @see #hasStart()
     */
    @Nullable
    public Long getStart() {
        return start;
    }

    /**
     * Returns the end timestamp from this operation.
     *
     * @return The end timestamp from this operation, may be {@code null}.
     * @see #hasEnd()
     */
    @Nullable
    public Long getEnd() {
        return end;
    }

    /**
     * Returns whether a start timestamp was supplied to this operation.
     *
     * @return {@code true} if a start timestamp was supplied to this operation.
     */
    public boolean hasStart() {
        return (start != null);
    }

    /**
     * Returns whether an end timestamp was supplied to this operation.
     *
     * @return {@code true} if an end timestamp was supplied to this operation.
     */
    public boolean hasEnd() {
        return (end != null);
    }

}