All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.guise.framework.component.ResourceCollectControl Maven / Gradle / Ivy

There is a newer version: 0.5.3
Show newest version
/*
 * Copyright © 2005-2008 GlobalMentor, Inc. 
 *
 * 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.guise.framework.component;

import java.net.URI;
import java.util.*;
import static java.util.Collections.*;
import static java.util.Objects.*;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.globalmentor.io.Files.*;
import static com.globalmentor.java.Classes.*;
import static com.globalmentor.net.URIs.*;

import com.globalmentor.event.EventListenerManager;
import com.globalmentor.model.TaskState;
import com.globalmentor.net.URIs;

import io.guise.framework.*;
import io.guise.framework.event.*;
import io.guise.framework.model.*;

/**
 * Control that allows resources to be collected and received at a given path. The destination path should reference a registered
 * {@link ResourceWriteDestination} of the application.
 * @author Garret Wilson
 */
public class ResourceCollectControl extends AbstractControl {

	/** The bound property of the paths of the collected resources. */
	public static final String RESOURCE_PATHS_PROPERTY = getPropertyName(ResourceCollectControl.class, "resourcePaths");
	/** The bound property of the state of receiving collected resources. */
	public static final String STATE_PROPERTY = getPropertyName(ResourceCollectControl.class, "state");

	@Override
	@SuppressWarnings("unchecked")
	public Depictor getDepictor() {
		return (Depictor)super.getDepictor();
	}

	/** The state of receiving resources, or null if receiving has not been initiated. */
	private TaskState state = null;

	/** @return The state of receiving resources, or null if receiving has not been initiated. */
	public TaskState getState() {
		return state;
	}

	/**
	 * Sets the state of receiving resources. This method is called by the associated depictor and should normally not be called directly by applications. This is
	 * a bound property.
	 * @param newSendState The new state of receiving resources, or null if receiving has not been initiated.
	 * @see #STATE_PROPERTY
	 */
	public void setState(final TaskState newSendState) {
		if(state != newSendState) { //if the value is really changing
			final TaskState oldState = state; //get the old value
			state = newSendState; //actually change the value
			firePropertyChange(STATE_PROPERTY, oldState, newSendState); //indicate that the value changed
		}
	}

	/** The paths of the currently collected resources. */
	private List resourcePaths = new CopyOnWriteArrayList();

	/**
	 * Returns the paths of the currently collected resources. These paths are for identification only, and are not guaranteed to represent any location
	 * accessible from the application.
	 * @return The the paths of the currently collected resources.
	 */
	public List getResourcePaths() {
		return unmodifiableList(resourcePaths);
	}

	/**
	 * Adds a new resource path. This method changes a bound property of type {@link List} holding type {@link String}. This method is called by the framework and
	 * normally this should not be called directly from applications. Manually adding a new resource path, depending on the platform, may not actually result in
	 * another resource being collected absent user intervention.
	 * @param resourcePath The resource path to add.
	 * @throws NullPointerException if the given resource path is null.
	 * @see #RESOURCE_PATHS_PROPERTY
	 */
	public void addResourcePath(final String resourcePath) {
		resourcePaths.add(requireNonNull(resourcePath, "Resource path cannot be null."));
		final List newList = unmodifiableList(new ArrayList(resourcePaths)); //create an unmodifiable copy of the resource paths
		firePropertyChange(RESOURCE_PATHS_PROPERTY, null, newList); //indicate that the value changed			
	}

	/**
	 * Removes a resource path. This method changes a bound property of type {@link List} holding type {@link String}. This method is called by the framework and
	 * normally this should not be called directly from applications. //TODO fix to actually tell the browser control that the path has changed Manually adding a
	 * new resource path, depending on the platform, may not actually result in another resource being collected absent user intervention.
	 * @param resourcePath The resource path to remove.
	 * @throws NullPointerException if the given resource path is null.
	 * @see #RESOURCE_PATHS_PROPERTY
	 */
	public void removeResourcePath(final String resourcePath) {
		resourcePaths.remove(requireNonNull(resourcePath, "Resource path cannot be null."));
		final List newList = unmodifiableList(new ArrayList(resourcePaths)); //create an unmodifiable copy of the resource paths
		firePropertyChange(RESOURCE_PATHS_PROPERTY, null, newList); //indicate that the value changed			
	}

	/**
	 * Clears all resource paths. This method changes a bound property of type {@link List} holding type {@link String}. This method is called by the framework
	 * and normally this should not be called directly from applications. //TODO fix to actually tell the browser control that the path has changed Manually
	 * adding a new resource path, depending on the platform, may not actually result in another resource being collected absent user intervention.
	 * @see #RESOURCE_PATHS_PROPERTY
	 */
	public void clearResourcePaths() {
		resourcePaths.clear(); //clear the resource paths
		final List newList = unmodifiableList(new ArrayList(resourcePaths)); //create an unmodifiable copy of the resource paths
		firePropertyChange(RESOURCE_PATHS_PROPERTY, null, newList); //indicate that the value changed			
	}

	/** The destination path relative to the application context path, of null if no resources are currently being sent. */
	private String destinationPath = null;

	/**
	 * Indicates the destination path relative to the application context path.
	 * @return The path representing the destination of the collected resources, or null if no resources are currently being sent.
	 */
	public String getDestinationPath() {
		return destinationPath;
	}

	/**
	 * The bookmark being used in receiving the resources at the destination path, or null if there is no bookmark specified and/or no resources are
	 * currently being sent.
	 */
	private Bookmark destinationBookmark = null;

	/**
	 * @return The bookmark being used in receiving the resources at the destination path, or null if there is no bookmark specified and/or no
	 *         resources are currently being sent.
	 */
	public Bookmark getDestinationBookmark() {
		return destinationBookmark;
	}

	/** Default constructor with a default models. */
	public ResourceCollectControl() {
		this(new DefaultInfoModel(), new DefaultEnableable()); //construct the class with default models
	}

	/**
	 * Info model and enableable object constructor.
	 * @param infoModel The component info model.
	 * @param enableable The enableable object in which to store enabled status.
	 * @throws NullPointerException if the given info model and/or enableable object is null.
	 */
	public ResourceCollectControl(final InfoModel infoModel, final Enableable enableable) {
		super(infoModel, enableable); //construct the parent class
	}

	/**
	 * Receives collected resources at the given destination path with no bookmark.
	 * @param destinationPath The path representing the destination of the collected resources, relative to the application.
	 * @throws NullPointerException if the given path is null.
	 * @throws IllegalArgumentException if the provided path specifies a URI scheme (i.e. the URI is absolute) and/or authority.
	 */
	public void receiveResources(final String destinationPath) {
		receiveResources(destinationPath, null); //send the resources with no bookmark
	}

	/**
	 * Receives collected resources at the given destination path using the given bookmark. If the resources are currently started to be received or already being
	 * received, no action occurs.
	 * @param destinationPath The path representing the destination of the collected resources, relative to the application.
	 * @param destinationBookmark The bookmark to be used in receiving the resources at the destination path, or null if no bookmark should be used.
	 * @throws NullPointerException if the given path is null.
	 * @throws IllegalArgumentException if the provided path specifies a URI scheme (i.e. the URI is absolute) and/or authority.
	 * @throws IllegalArgumentException if the provided path is absolute.
	 */
	public void receiveResources(final String destinationPath, final Bookmark destinationBookmark) {
		final TaskState sendState = getState(); //get the current send state
		if(sendState != TaskState.INITIALIZE && sendState != TaskState.INCOMPLETE) { //if the transfer has not yet started
			setState(TaskState.INITIALIZE); //show that we're initializing the transfer
			this.destinationPath = checkRelativePath(destinationPath); //save the path
			this.destinationBookmark = destinationBookmark; //save the bookmark
			getDepictor().receive(createPathURI(destinationPath), destinationBookmark); //tell the depictor to start receiving
		}
	}

	/**
	 * Cancels any currently occurring resource transfers. If the resources are not currently being transferred, no action occurs.
	 */
	public void cancelReceive() {
		final TaskState sendState = getState(); //get the current send state
		if(sendState == TaskState.INCOMPLETE) { //if a transfer is occurring
			getDepictor().cancel(); //tell the depictor to cancel
		}
	}

	/**
	 * Adds a progress listener.
	 * @param progressListener The progress listener to add.
	 */
	public void addProgressListener(final ProgressListener progressListener) {
		getEventListenerManager().add(ProgressListener.class, progressListener); //add the listener
	}

	/**
	 * Removes an progress listener.
	 * @param progressListener The progress listener to remove.
	 */
	public void removeProgressListener(final ProgressListener progressListener) {
		getEventListenerManager().remove(ProgressListener.class, progressListener); //remove the listener
	}

	/**
	 * Fires a progress event to all registered progress listeners. This method delegates to {@link #fireProgressed(ProgressEvent)}.
	 * @param task The task being performed, or null if not indicated.
	 * @param taskState The state of the task.
	 * @param value The current progress, or -1 if not known.
	 * @param maximumValue The goal, or -1 if not known.
	 * @throws NullPointerException if the given task state is null.
	 * @see ProgressListener
	 * @see ProgressEvent
	 */
	public void fireProgressed(final String task, final TaskState taskState, final long value, final long maximumValue) {
		//TODO put this stuff in a setProgress() method, and keep track of this information locally
		if(task != null && taskState == TaskState.COMPLETE) { //if we complete a file
			for(final String resourcePath : resourcePaths) { //look at the resource paths
				if(URIs.getName(resourcePath).equals(task)) { //if this resource path just finished TODO create a better way to check; this could result in inconsistencies if multiple paths have the same filename
					removeResourcePath(resourcePath); //remove this resource path
					break; //stop checking for matches
				}
			}
		}
		final EventListenerManager eventListenerManager = getEventListenerManager(); //get event listener support
		if(eventListenerManager.hasListeners(ProgressListener.class)) { //if there are progress listeners registered
			fireProgressed(new ProgressEvent(this, task, taskState, value, maximumValue)); //create and fire a new progress event
		}
	}

	/**
	 * Fires a given progress event to all registered progress listeners.
	 * @param progressEvent The progress event to fire.
	 */
	protected void fireProgressed(final ProgressEvent progressEvent) {
		for(final ProgressListener progressListener : getEventListenerManager().getListeners(ProgressListener.class)) { //for each progress listener
			progressListener.progressed(progressEvent); //dispatch the progress event to the listener
		}
	}

	/**
	 * The custom depictor type for web collect controls.
	 * @author Garret Wilson
	 * @param  The type of control to be depicted.
	 */
	public interface Depictor extends io.guise.framework.platform.Depictor {

		/**
		 * Requests that resource collection start.
		 * @param destinationURI The URI representing the destination of the collected resources, relative to the application.
		 * @param destinationBookmark The bookmark to be used in receiving the resources at the destination path, or null if no bookmark should be
		 *          used.
		 * @throws NullPointerException if the given destination URI is null.
		 */
		public void receive(URI destinationURI, final Bookmark destinationBookmark);

		/** Requests that resource collection be canceled. */
		public void cancel();

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy