/*******************************************************************************
* Copyright 2013 Geoscience Australia
*
* 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 au.gov.ga.earthsci.intent;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.content.IContentType;
/**
* Description of an intent to be performed. Plugins can define an
* {@link IntentFilter} that can handle matching intents.
* <p/>
* Modelled on Android's Intent system.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class Intent
{
private String action;
private final Set<String> categories = new HashSet<String>();
private URI uri;
private IContentType contentType;
private boolean determineContentType = true;
private Class<?> expectedReturnType;
private Class<?> requiredReturnType;
private Class<? extends IIntentHandler> handler;
private final Map<String, Object> extras = new HashMap<String, Object>();
private int flags;
/**
* @return Action to be performed.
*/
public String getAction()
{
return action;
}
/**
* Set the action that this intent performs.
*
* @param action
* @return this
*/
public Intent setAction(String action)
{
this.action = action;
return this;
}
/**
* @return Categories associated with this intent.
*/
public Set<String> getCategories()
{
return categories;
}
/**
* Add a category to this intent.
*
* @param category
* @return this
*/
public Intent addCategory(String category)
{
categories.add(category);
return this;
}
/**
* Remove a category from this intent.
*
* @param category
* @return this
*/
public Intent removeCategory(String category)
{
categories.remove(category);
return this;
}
/**
* @return The URI of the data associated with this intent.
*/
public URI getURI()
{
return uri;
}
/**
* Set the URI of the data associated with this intent.
* <p/>
* This value may be updated during the Intent lifecycle (to support URI
* re-writing etc.).
*
* @param uri
* @return this
*/
public Intent setURI(URI uri)
{
this.uri = uri;
return this;
}
/**
* @return Explicit content type of the data associated with this intent.
*/
public IContentType getContentType()
{
return contentType;
}
/**
* Set the explicit content type of the data associated with this intent.
*
* @param type
* @return this
*/
public Intent setContentType(IContentType contentType)
{
this.contentType = contentType;
return this;
}
/**
* @return If a content type is not set, should it be determined?
*/
public boolean isDetermineContentType()
{
return determineContentType;
}
/**
* Set if the content type should be determined if it is not set. Defaults
* to true.
* <p/>
* If this is true, and the content type cannot be determined, the intent
* will fail. This should be true when using an intent to open a resource,
* so that the intent manager can match the correct intent filter to the
* resource's content type.
*
* @param determineContentType
*/
public void setDetermineContentType(boolean determineContentType)
{
this.determineContentType = determineContentType;
}
/**
* @return A URL pointing to the resource identified by this Intent's URI.
* @throws MalformedURLException
*/
public URL getURL() throws MalformedURLException
{
if (getURI() == null)
{
return null;
}
return uri.toURL();
}
/**
* @return The expected type of the object returned by the intent handler.
*/
public Class<?> getExpectedReturnType()
{
return expectedReturnType;
}
/**
* Set the expected type of the object returned by the intent handler.
*
* @param expectedReturnType
* @return this
*/
public Intent setExpectedReturnType(Class<?> expectedReturnType)
{
this.expectedReturnType = expectedReturnType;
return this;
}
/**
* @return The type of the object required to be returned by the intent
* handler.
*/
public Class<?> getRequiredReturnType()
{
return requiredReturnType;
}
/**
* Set the required return type of the object returned by the intent
* handler.
*
* @param requiredReturnType
* @return this
*/
public Intent setRequiredReturnType(Class<?> requiredReturnType)
{
this.requiredReturnType = requiredReturnType;
return this;
}
/**
* @return The explicit handler class used to handle this intent.
*/
public Class<? extends IIntentHandler> getHandler()
{
return handler;
}
/**
* Set the handler class used to handle this intent explicitly. If this is
* set, no other fields are required, as the {@link IntentFilter}s will not
* be searched to find an appropriate handler.
*
* @param handler
* @return this
*/
public Intent setHandler(Class<? extends IIntentHandler> handler)
{
this.handler = handler;
return this;
}
/**
* @return Integer flags set on this intent.
*/
public int getFlags()
{
return flags;
}
/**
* Set the flags for this intent.
*
* @param flags
* @return this
*/
public Intent setFlags(int flags)
{
this.flags = flags;
return this;
}
/**
* Add a flag to this intent. Uses a bitwise OR.
*
* @param flag
* @return this
*/
public Intent addFlag(int flag)
{
flags = flags | flag;
return this;
}
/**
* Check if the given flag is set on this intent, using a bitwise AND.
*
* @param flag
* @return True if the given flag is set on this intent.
*/
public boolean hasFlag(int flag)
{
return (flags & flag) == flag;
}
/**
* @return The extra data map associated with this intent.
*/
public Map<String, Object> getExtras()
{
return extras;
}
/**
* Lookup an extra by the given key on this intent.
*
* @param key
* @return Extra object associated with the given key on this intent.
*/
public Object getExtra(String key)
{
return extras.get(key);
}
/**
* Set an extra keyed by the given key on this intent.
*
* @param key
* @param value
* @return this
*/
public Intent putExtra(String key, Object value)
{
extras.put(key, value);
return this;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
if (action != null)
{
sb.append(", action: " + action); //$NON-NLS-1$
}
if (!categories.isEmpty())
{
sb.append(", categories: " + Arrays.toString(categories.toArray())); //$NON-NLS-1$
}
if (uri != null)
{
sb.append(", URI: " + uri); //$NON-NLS-1$
}
if (contentType != null)
{
sb.append(", content-type: " + contentType.getId()); //$NON-NLS-1$
}
if (expectedReturnType != null)
{
sb.append(", expected return-type: " + expectedReturnType.getName()); //$NON-NLS-1$
}
if (requiredReturnType != null)
{
sb.append(", required return-type: " + requiredReturnType.getName()); //$NON-NLS-1$
}
return String.format("%s [%s]", getClass().getSimpleName(), sb.length() > 0 ? sb.substring(2) : ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}