org.thevortex.lighting.jinks.client.AbstractWinkService.java Source code

Java tutorial

Introduction

Here is the source code for org.thevortex.lighting.jinks.client.AbstractWinkService.java

Source

/*
 * Copyright (c) 2014 by the author(s).
 *
 * 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 org.thevortex.lighting.jinks.client;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thevortex.lighting.jinks.Subscription;
import org.thevortex.lighting.jinks.WinkObject;

/**
 * Simple framework for most service points.
 *
 * @author E. A. Graham Jr.
 */
public abstract class AbstractWinkService<T extends WinkObject> implements WinkService<T> {
    public static final String ME = "/users/me/";
    protected final WinkClient client;
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final PubNubServiceNotifier<T> notifier;
    private boolean enableNotify = false;

    public AbstractWinkService(WinkClient client) {
        this.client = client;
        notifier = new PubNubServiceNotifier<>(endpoint(), this::parseItem);
    }

    @Override
    public void enableNotifications(boolean enableNotify) {
        this.enableNotify = enableNotify;
    }

    @Override
    public void close() {
        if (notifier != null)
            notifier.close();
    }

    /**
     * {@inheritDoc}
     * <p>
     * Also initializes listening for events if not already started. This implies the
     * service subscription does not change over the run-time of the application.
     * </p>
     */
    @Override
    public SortedSet<T> getAll() throws IOException {
        // TODO paginate
        SortedSet<T> result = new TreeSet<>();
        Set<Subscription> itemSubscriptions = new HashSet<>();
        Subscription serviceSubscription = null;

        ObjectNode data = (ObjectNode) client.doGet(ME + endpoint());
        if (data.has("data")) {
            ArrayNode jsonList = (ArrayNode) data.get("data");

            for (JsonNode jsonNode : jsonList) {
                T item = parseItem(jsonNode);
                if (item != null) {
                    result.add(item);
                    Subscription subscription = item.getSubscription();
                    if (subscription != null)
                        itemSubscriptions.add(subscription);
                }
            }
        }

        if (data.has("subscription")) {
            serviceSubscription = WinkClient.MAPPER.convertValue(data.get("subscription"), Subscription.class);
        }

        // if the notifier is enabled, start it up
        if (enableNotify)
            notifier.init(serviceSubscription, itemSubscriptions);
        else if (notifier != null)
            notifier.close();
        return result;
    }

    /**
     * @param data the thing to make
     * @return the thing post creation
     * @throws IOException
     */
    public T create(T data) throws IOException {
        String payload = WinkClient.MAPPER.writeValueAsString(data);
        JsonNode response = client.doPost(ME + endpoint(), payload);
        return parseItem(response);
    }

    @Override
    public T get(String id) throws IOException {
        JsonNode jsonNode = client.doGet(makeUri(id));
        return parseItem(jsonNode);
    }

    /**
     * @param data the thing to update
     * @return the updated item
     * @throws IOException
     */
    public T update(T data) throws IOException {
        String payload = WinkClient.MAPPER.writeValueAsString(data);
        JsonNode response = client.doPut(makeUri(data.getId()), payload);
        // if we aren't getting responses, re-fetch to ensure freshness
        return response == null ? get(data.getId()) : parseItem(response);
    }

    /**
     * @param id the ID of the thing to delete
     * @throws IOException
     */
    public void delete(String id) throws IOException {
        client.doDelete(makeUri(id));
    }

    /**
     * @return the name of the thing we're talking to
     */
    protected abstract String endpoint();

    /**
     * @param jsonNode incoming
     * @return the thing from the data
     */
    public abstract T parseItem(JsonNode jsonNode);

    /**
     * How to make a URI for a single thing
     *
     * @param id the ID of the thing
     * @return the URI
     */
    protected String makeUri(String id) {
        return "/" + endpoint() + "/" + id;
    }

    @Override
    public void addServiceChangeListener(ServiceChangeListener<T> listener) {
        notifier.addServiceChangeListener(listener);
    }

    @Override
    public void removeServiceChangeListener(ServiceChangeListener<T> listener) {
        notifier.removeServiceChangeListener(listener);
    }
}