de.nava.informa.utils.ChannelRegistry.java Source code

Java tutorial

Introduction

Here is the source code for de.nava.informa.utils.ChannelRegistry.java

Source

//
// Informa -- RSS Library for Java
// Copyright (c) 2002 by Niko Schmuck
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//

package de.nava.informa.utils;

import de.nava.informa.core.CategoryIF;
import de.nava.informa.core.ChannelBuilderIF;
import de.nava.informa.core.ChannelGroupIF;
import de.nava.informa.core.ChannelIF;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;

/**
 * This class can be used as central repository for storing a
 * collection of channel objects and maintaining them (by specifying
 * update intervals).
 *
 * @author Niko Schmuck
 */
public class ChannelRegistry {

    private static Log logger = LogFactory.getLog(ChannelRegistry.class);
    public static final int DEFAULT_ACCEPT_NR_ERRORS = 10;

    private int acceptNrOfErrors;
    private ChannelBuilderIF builder;
    private ChannelGroupIF channels;
    private Timer updateDaemon;
    private Map<URL, UpdateChannelTask> updateTasks;
    private Map<URL, UpdateChannelInfo> channelInfos;

    /**
     * Constructor for a new ChannelRegistry object, the new items found by
     * scanning the are created using the given <code>builder</code>.
     *
     * @param builder The ChannelBuilderIF to use for creating news items.
     */
    public ChannelRegistry(ChannelBuilderIF builder) {
        this.builder = builder;
        this.channels = builder.createChannelGroup("Default");
        // start a new timer 'daemon' which controls updating tasks
        updateDaemon = new Timer(true);
        updateTasks = new HashMap<>();
        channelInfos = new HashMap<>();
        acceptNrOfErrors = DEFAULT_ACCEPT_NR_ERRORS;
    }

    /**
     * Adds one new channel object (instantiated with the help of the
     * given URL from where the channel can be retrieved from) to the
     * registry.
     *
     * @param url      - the URL where the channel news can be retrieved.
     * @param interval - time in seconds between update retrieval.
     * @param active   - wether regular updates should be executed.
     */
    public ChannelIF addChannel(URL url, int interval, boolean active) {
        return addChannel(url, null, interval, active);
    }

    /**
     * Adds one new channel object in the given category to the
     * registry.
     *
     * @param url        - the URL where the channel news can be retrieved.
     * @param categories - the categories to which this channel should be
     *                   added to (collection of CategoryIF objects).
     * @param interval   - time in seconds between update retrieval.
     * @param active     - wether regular updates should be executed.
     */
    public ChannelIF addChannel(URL url, Collection<CategoryIF> categories, int interval, boolean active) {

        ChannelIF channel = builder.createChannel("[uninitialized channel]");
        channel.setCategories(categories);
        channel.setLocation(url);

        channel = addChannel(channel, active, interval);
        return channel;
    }

    /**
     * Given a stand-alone Channel (i.e. just read in from disk) we
     * add it into the ChannelGroup and activated if necessary.
     *
     * @param channel  - Fully realized Channel
     * @param active   - Same as above
     * @param interval - Same as above
     */
    public ChannelIF addChannel(ChannelIF channel, boolean active, int interval) {
        channels.add(channel);
        logger.debug("added channel " + channel.getId() + " to registry");
        if (active) {
            activateChannel(channel, interval);
        }
        return channel;
    }

    /**
     * Activates a channel and looks for new items for the given channel.
     *
     * @param channel  The ChannelIF to scan for updates
     * @param interval Difference between channel updates in seconds
     */
    public void activateChannel(ChannelIF channel, int interval) {
        // TODO: what about changed interval setting?
        //       (workaround, deactivate, set interval, activate again)
        // only create one update task per channel
        if (updateTasks.get(channel.getLocation()) == null) {
            // auto-deactivation after 10 times an channel parse error occurred
            UpdateChannelInfo info = channelInfos.get(channel.getLocation());
            if (info == null) {
                info = new UpdateChannelInfo(acceptNrOfErrors);
                info.setFormatDetected(false);
                channelInfos.put(channel.getLocation(), info);
            } else {
                info.reset();
            }
            // create new task
            UpdateChannelTask task = new UpdateChannelTask(this, builder, channel, info);
            // schedule the task for periodic execution, first time after
            // 100 ms, and then regularly in <interval> secs.
            updateDaemon.schedule(task, 100, interval * 1000);
            logger.info("activating channel updates for " + channel.getTitle());
            updateTasks.put(channel.getLocation(), task);
            // TODO: Adapt to new UserIF
            // channel.getSubscription().setActive(true);
            // channel.getSubscription().setUpdateInterval(interval);
        }
    }

    public ChannelIF getChannel(long id) {
        return channels.getById(id);
    }

    /**
     * Gets all the channels in the registry.
     *
     * @return A collection of ChannelIF objects.
     */
    public Collection getChannels() {
        return channels.getAll();
    }

    public ChannelGroupIF getChannelGroup() {
        return channels;
    }

    public void setChannelGroup(ChannelGroupIF channels) {
        this.channels = channels;
        // === TODO: Adapt to new UserIF
        // -- loop over channels and activate if necessary
        // Iterator it = channels.getAll().iterator();
        // while (it.hasNext()) {
        //   ChannelIF channel = (ChannelIF) it.next();
        //   if (channel.getSubscription().isActive()) {
        //        activateChannel(channel,
        //                        channel.getSubscription().getUpdateInterval());
        //   }
        // }
    }

    /**
     * Removes a channel from the registry. First it is cleanly deactivated.
     *
     * @param channel The ChannelIF object to remove.
     */
    public void removeChannel(ChannelIF channel) {
        deactivateChannel(channel);
        channels.remove(channel);
        logger.debug("removing channel from registry: " + channel.getTitle());
    }

    /**
     * Deactivates a channel, no more updates are made.
     */
    public void deactivateChannel(ChannelIF channel) {
        UpdateChannelTask task = updateTasks.get(channel.getLocation());
        if (task != null) {
            logger.debug("update task canceled for " + channel.getTitle());
            task.cancel();
            updateTasks.remove(channel.getLocation());
            // TODO: Adapt to new UserIF
            //   channel.getSubscription().setActive(false);
        }
    }

    /**
     * Returns wether the channel update task is still active or not.
     */
    public boolean isActiveChannel(ChannelIF channel) {
        UpdateChannelTask task = updateTasks.get(channel.getLocation());
        return (task != null);
    }

    public UpdateChannelInfo getUpdateInfo(ChannelIF channel) {
        return channelInfos.get(channel.getLocation());
    }

    /**
     * Gets the scheduled time of the next channel update.
     *
     * @param channel The ChannelIF to retrieve information for.
     * @return The date of the next execution, 0 if not available
     */
    public long getScheduledUpdateTime(ChannelIF channel) {
        UpdateChannelTask task = updateTasks.get(channel.getLocation());
        if (task != null) {
            return task.scheduledExecutionTime();
        }
        return 0;
    }

    public int getAcceptNrOfErrors() {
        return acceptNrOfErrors;
    }

    /**
     * Set number of channel parser errors acceptable after channel is not
     * longer automatically updated.
     */
    public void setAcceptNrOfErrors(int acceptNrOfErrors) {
        this.acceptNrOfErrors = acceptNrOfErrors;
    }

}